NishilSheth

room.js

Sep 23rd, 2023
17
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const Room = () => {
  2.     const {
  3.         hasWindow,
  4.         setHasWindow,
  5.         isPlayerReady,
  6.         setIsPlayerReady,
  7.         play,
  8.         setPlay,
  9.         isFullScreen,
  10.         setIsFullScreen,
  11.         volume,
  12.         setVolume,
  13.         url,
  14.         setUrl,
  15.         isDropdownOpen,
  16.         setIsDropdownOpen,
  17.         speed,
  18.         setSpeed,
  19.         playtime,
  20.         setPlaytime,
  21.         setActiveMenu,
  22.         fileUrl,
  23.         setFileUrl,
  24.     } = useContext(playerContext);
  25.  
  26.     const [showControls, setShowControls] = useState(true);
  27.     const [isMouseVisible, setIsMouseVisible] = useState(true);
  28.     const [isRoomConnected, setIsRoomConnected] = useState(false);
  29.     const [message, setMessage] = useState("");
  30.     const [room, setRoom] = useState("");
  31.     const timerRef = useRef(null);
  32.  
  33.     const playerRef = useRef();
  34.     const rangeInputRef = useRef();
  35.     const vidSectionRef = useRef();
  36.     const fullScreenBtnRef = useRef();
  37.     const volumeInputRef = useRef();
  38.     const urlInputRef = useRef();
  39.     const socket = useRef(null);
  40.  
  41.     const ChatMessage = useRef();
  42.     const controlsDeactivationTime = 3000;
  43.     const router = useRouter();
  44.  
  45.     const handlePlayerReady = () => {
  46.         if (playerRef.current) {
  47.             setIsPlayerReady(true);
  48.         }
  49.     };
  50.  
  51.     const handleRangeChange = (e) => {
  52.         playerRef.current.seekTo(e.target.value, "seconds");
  53.         setPlaytime(e.target.value);
  54.         socket.current.emit("update-progress", roomID, e.target.value);
  55.     };
  56.  
  57.     const handleProgressChange = () => {
  58.         // get the current time of video
  59.         // update the value of range input to current time of video
  60.         if (rangeInputRef.current) {
  61.             rangeInputRef.current.value = Math.round(
  62.                 playerRef.current.getCurrentTime()
  63.             );
  64.             if (
  65.                 formatTime(playerRef.current.getDuration()) ===
  66.                 formatTime(Math.round(playerRef.current.getCurrentTime()))
  67.             ) {
  68.                 setPlay(false);
  69.             }
  70.         }
  71.         setPlaytime(Math.round(playerRef.current.getCurrentTime()));
  72.     };
  73.  
  74.     const handleOnPlay = () => {
  75.         setPlay(true);
  76.         socket.current.emit("play-video", roomID);
  77.     };
  78.  
  79.     const handleOnPause = () => {
  80.         setPlay(false);
  81.         socket.current.emit("pause-video", roomID);
  82.     };
  83.  
  84.     const handleFullScreen = (e) => {
  85.         if (isFullScreen) {
  86.             if (document.exitFullscreen) {
  87.                 document.exitFullscreen();
  88.             }
  89.         } else {
  90.             if (vidSectionRef.current.requestFullscreen) {
  91.                 vidSectionRef.current.requestFullscreen();
  92.                 document.activeElement.blur(); // remove focus from the fullscreen button
  93.             }
  94.         }
  95.     };
  96.  
  97.     const toggleFullscreen = () => {
  98.         if (vidSectionRef.current) {
  99.             if (!(document.fullscreenElement === vidSectionRef.current)) {
  100.                 vidSectionRef.current.requestFullscreen();
  101.             } else {
  102.                 if (document.exitFullscreen) {
  103.                     document.exitFullscreen();
  104.                 }
  105.             }
  106.             setIsFullScreen(!isFullScreen);
  107.         }
  108.     };
  109.     const togglePlayState = () => {
  110.         setPlay((prevPlay) => !prevPlay);
  111.         document.activeElement.blur();
  112.         // setShowControls(true);
  113.     };
  114.  
  115.     const handleVolumeChange = (e) => {
  116.         setVolume(parseFloat(e.target.value));
  117.     };
  118.  
  119.     const handleMouseMove = () => {
  120.         clearTimeout(timerRef.current);
  121.         setShowControls(true);
  122.         setIsMouseVisible(true);
  123.  
  124.         timerRef.current = setTimeout(() => {
  125.             setShowControls(false);
  126.             setIsDropdownOpen(false);
  127.             setIsMouseVisible(false);
  128.         }, controlsDeactivationTime); // Adjust the timeout value according to your preference (in milliseconds)
  129.     };
  130.  
  131.     const formatTime = (seconds) => {
  132.         const date = new Date(null);
  133.         date.setSeconds(seconds);
  134.         if (date instanceof Date && !isNaN(date)) {
  135.             // Checking for a valid date object.
  136.             if (seconds > 3600) {
  137.                 return date.toISOString().slice(-13, -5);
  138.             } else {
  139.                 return date.toISOString().slice(-10, -5);
  140.             }
  141.         }
  142.     };
  143.  
  144.     useEffect(() => {
  145.         if (typeof window !== "undefined") {
  146.             setHasWindow(true);
  147.         }
  148.  
  149.         const handleFullScreenChange = () => {
  150.             setIsFullScreen(
  151.                 document.fullscreenElement === vidSectionRef.current
  152.             );
  153.         };
  154.  
  155.         // using debounce to prevent this from firing a lot of times if the arrow keys are pressed rapidly.
  156.         const handleKeyPress = debounce((event) => {
  157.             const activeElement = document.activeElement;
  158.             const excludedTags = ["INPUT", "TEXTAREA", "SELECT"];
  159.             if (
  160.                 excludedTags.includes(activeElement.tagName) &&
  161.                 !(activeElement.type === "range")
  162.             ) {
  163.                 return;
  164.             }
  165.  
  166.             switch (event.key) {
  167.                 case "f":
  168.                     toggleFullscreen();
  169.                     break;
  170.                 case " ":
  171.                     event.preventDefault();
  172.                     togglePlayState();
  173.                     handleMouseMove();
  174.                     break;
  175.  
  176.                 default:
  177.                     break;
  178.             }
  179.         }, 250);
  180.  
  181.         document.addEventListener("keydown", handleKeyPress);
  182.  
  183.         document.addEventListener("fullscreenchange", handleFullScreenChange);
  184.  
  185.         // Cleanup
  186.         return () => {
  187.             document.removeEventListener(
  188.                 "fullscreenchange",
  189.                 handleFullScreenChange
  190.             );
  191.             document.removeEventListener("keydown", handleKeyPress);
  192.             handleKeyPress.cancel();
  193.         };
  194.     }, []);
  195.  
  196.     useEffect(() => {
  197.         if (vidSectionRef.current) {
  198.             vidSectionRef.current.addEventListener(
  199.                 "mousemove",
  200.                 handleMouseMove
  201.             );
  202.         }
  203.  
  204.         return () => {
  205.             if (vidSectionRef.current) {
  206.                 vidSectionRef.current.removeEventListener(
  207.                     "mousemove",
  208.                     handleMouseMove
  209.                 );
  210.             }
  211.             clearTimeout(timerRef.current);
  212.         };
  213.     }, [vidSectionRef.current]);
  214.  
  215.     const roomID = router.query.id;
  216.     useEffect(() => {
  217.         if (roomID) {
  218.             // Use the socket ID to join the room
  219.             // You can establish the socket connection here and join the room
  220.             socket.current = io("http://localhost:8080");
  221.             // Join a room using the socket ID
  222.             socket.current.on("connect", () => {
  223.                 socket.current.emit("join-room", roomID, (response) => {
  224.                     if (response.success) {
  225.                         setIsRoomConnected(true);
  226.                     }
  227.                 });
  228.             });
  229.             socket.current.on("update-url", (roomID, url) => {
  230.                 setUrl(url);
  231.             });
  232.  
  233.             socket.current.on("play-video", (roomID) => {
  234.                 setPlay(true);
  235.             });
  236.             socket.current.on("pause-video", (roomID) => {
  237.                 setPlay(false);
  238.             });
  239.  
  240.             socket.current.on("update-progress", (roomID, progress) => {
  241.                 setPlaytime(Math.round(progress));
  242.                 if (playerRef.current) {
  243.                     playerRef.current.seekTo(progress, "seconds");
  244.                 }
  245.             });
  246.  
  247.             socket.current.on("disconnect", () => {
  248.                 setUrl("");
  249.             });
  250.         }
  251.     }, [roomID]);
  252.  
  253.     useEffect(() => {
  254.         if (isPlayerReady && playerRef.current && playtime !== null) {
  255.             playerRef.current.seekTo(playtime, "seconds");
  256.         }
  257.     }, [isPlayerReady, playtime]);
  258.  
  259.     const handleSubmit = () => {
  260.         setUrl(urlInputRef.current.value);
  261.         setFileUrl("");
  262.         socket.current.emit("update-url", roomID, urlInputRef.current.value);
  263.     };
  264.  
  265.     return (
  266.         <main className="mb-5 mt-7 flex flex-col gap-6 px-5 md:flex-row">
  267.             {/* Section 1: Video */}
  268.             {isRoomConnected && (
  269.                 <div
  270.                     className={`flex w-full flex-col gap-2 md:w-2/3 ${
  271.                         isFullScreen
  272.                             ? isMouseVisible
  273.                                 ? ""
  274.                                 : "cursor-none"
  275.                             : ""
  276.                     }`}
  277.                 >
  278.                     <div>
  279.                         <Tab.Group>
  280.                             <Tab.List className="flex h-12 items-center gap-4 rounded-md bg-gray-200 p-2">
  281.                                 <Tab as={Fragment}>
  282.                                     {({ selected }) => (
  283.                                         <button
  284.                                             className={`${
  285.                                                 selected ? "bg-black/20" : ""
  286.                                             } rounded-md px-2 py-1 outline-none transition-colors hover:bg-black/20`}
  287.                                         >
  288.                                             Video URL
  289.                                         </button>
  290.                                     )}
  291.                                 </Tab>
  292.                                 <Tab as={Fragment}>
  293.                                     {({ selected }) => (
  294.                                         <button
  295.                                             className={`${
  296.                                                 selected ? "bg-black/20" : ""
  297.                                             } rounded-md px-2 py-1 outline-none transition-colors hover:bg-black/20`}
  298.                                         >
  299.                                             Custom Video
  300.                                         </button>
  301.                                     )}
  302.                                 </Tab>
  303.                             </Tab.List>
  304.                             <Tab.Panels>
  305.                                 <Tab.Panel className="mt-2 flex gap-2">
  306.                                     <input
  307.                                         ref={urlInputRef}
  308.                                         type="text"
  309.                                         className="w-full rounded-md border border-gray-400 bg-transparent px-3 py-2 font-light text-white outline-none placeholder:font-light"
  310.                                         placeholder="Enter Video URL here."
  311.                                     />
  312.                                     <button
  313.                                         onClick={handleSubmit}
  314.                                         className="rounded-md bg-red-600 px-2 py-1 text-white"
  315.                                     >
  316.                                         Submit
  317.                                     </button>
  318.                                 </Tab.Panel>
  319.  
  320.                                 <Tab.Panel className="mt-2">
  321.                                     <label
  322.                                         htmlFor="file-choose"
  323.                                         className="cursor-pointer rounded-md bg-red-600 px-3 py-2 text-left text-white"
  324.                                     >
  325.                                         Choose File
  326.                                         <input
  327.                                             accept="video/*"
  328.                                             onChange={(e) => {
  329.                                                 const file = e.target.files[0];
  330.                                                 if (file) {
  331.                                                     const videoUrl =
  332.                                                         URL.createObjectURL(
  333.                                                             file
  334.                                                         );
  335.                                                     setFileUrl(videoUrl);
  336.                                                     setUrl("");
  337.                                                 }
  338.                                             }}
  339.                                             id="file-choose"
  340.                                             type="file"
  341.                                             className="w-0 opacity-0"
  342.                                         />
  343.                                     </label>
  344.                                 </Tab.Panel>
  345.                             </Tab.Panels>
  346.                         </Tab.Group>
  347.                     </div>
  348.                     <section
  349.                         ref={vidSectionRef}
  350.                         className="relative flex w-full select-none flex-col gap-3"
  351.                     >
  352.                         {hasWindow && (
  353.                             <>
  354.                                 {url && (
  355.                                     <ReactPlayer
  356.                                         ref={playerRef}
  357.                                         url={url}
  358.                                         onReady={handlePlayerReady}
  359.                                         config={{
  360.                                             youtube: {
  361.                                                 playerVars: { disablekb: 1 },
  362.                                             },
  363.                                         }}
  364.                                         className="pointer-events-none aspect-video"
  365.                                         width="100%"
  366.                                         height="100%"
  367.                                         playing={play}
  368.                                         onProgress={handleProgressChange}
  369.                                         onPlay={handleOnPlay}
  370.                                         onPause={handleOnPause}
  371.                                         volume={volume}
  372.                                         playbackRate={speed}
  373.                                     />
  374.                                 )}
  375.                                 {fileUrl && (
  376.                                     <ReactPlayer
  377.                                         ref={playerRef}
  378.                                         url={fileUrl}
  379.                                         onReady={handlePlayerReady}
  380.                                         className="pointer-events-none aspect-video"
  381.                                         width="100%"
  382.                                         height="100%"
  383.                                         playing={play}
  384.                                         onProgress={handleProgressChange}
  385.                                         onPlay={() => setPlay(true)}
  386.                                         onPause={() => setPlay(false)}
  387.                                         volume={volume}
  388.                                         playbackRate={speed}
  389.                                         config={{
  390.                                             file: {
  391.                                                 attributes: { controls: false },
  392.                                             },
  393.                                         }}
  394.                                     />
  395.                                 )}
  396.                             </>
  397.                         )}
  398.                         {/* Controls */}
  399.                         {isPlayerReady &&
  400.                             ReactPlayer.canPlay(url) |
  401.                                 ReactPlayer.canPlay(fileUrl) &&
  402.                             playerRef.current && (
  403.                                 <div
  404.                                     className={`${
  405.                                         showControls && "opacity-100"
  406.                                     } absolute bottom-0 flex w-full flex-col items-center gap-3 bg-gradient-to-t from-black via-black/70 to-transparent px-3 py-1 opacity-0 transition-opacity duration-300 md:px-5 md:py-2`}
  407.                                 >
  408.                                     <input
  409.                                         className="range-input w-full accent-red-600"
  410.                                         type="range"
  411.                                         min={0}
  412.                                         max={playerRef.current.getDuration()}
  413.                                         onChange={handleRangeChange}
  414.                                         ref={rangeInputRef}
  415.                                     />
  416.                                     <div className="flex w-full items-center gap-3">
  417.                                         <button onClick={() => setPlay(!play)}>
  418.                                             {play ? (
  419.                                                 <BsPauseFill className="text-3xl text-white" />
  420.                                             ) : (
  421.                                                 <BsFillPlayFill className="text-3xl text-white" />
  422.                                             )}
  423.                                         </button>
  424.                                         <button className="hidden md:block">
  425.                                             {volume > 0.5 ? (
  426.                                                 <BsVolumeUpFill className="text-3xl text-white" />
  427.                                             ) : volume > 0 ? (
  428.                                                 <BsVolumeDownFill className="text-3xl text-white" />
  429.                                             ) : (
  430.                                                 <BsVolumeMuteFill className="text-3xl text-white" />
  431.                                             )}
  432.                                         </button>
  433.                                         <input
  434.                                             className="volume-input hidden w-1/5 accent-red-600 md:block"
  435.                                             type="range"
  436.                                             min={0}
  437.                                             max={1}
  438.                                             step={"0.01"}
  439.                                             ref={volumeInputRef}
  440.                                             onChange={handleVolumeChange}
  441.                                         />
  442.                                         <span
  443.                                             className={`${poppins.className} mr-auto text-sm text-white`}
  444.                                         >
  445.                                             {formatTime(playtime)} /{" "}
  446.                                             {formatTime(
  447.                                                 playerRef.current.getDuration()
  448.                                             )}
  449.                                         </span>
  450.                                         <div className="absolute bottom-10 right-5">
  451.                                             <DropdownMenu />
  452.                                         </div>
  453.                                         <button
  454.                                             onClick={() => {
  455.                                                 setIsDropdownOpen(
  456.                                                     (prevState) => !prevState
  457.                                                 );
  458.                                                 setActiveMenu("main");
  459.                                             }}
  460.                                         >
  461.                                             <MdSettings className="text-2xl text-white" />
  462.                                         </button>
  463.                                         <button
  464.                                             ref={fullScreenBtnRef}
  465.                                             onClick={handleFullScreen}
  466.                                             // className="ml-auto"
  467.                                         >
  468.                                             {isFullScreen ? (
  469.                                                 <BsFullscreenExit className="text-xl text-white" />
  470.                                             ) : (
  471.                                                 <BsFullscreen className=" text-xl text-white" />
  472.                                             )}
  473.                                         </button>
  474.                                     </div>
  475.                                 </div>
  476.                             )}
  477.                     </section>
  478.                 </div>
  479.             )}
  480.         </main>
  481.     );
  482. };
Advertisement
Add Comment
Please, Sign In to add comment