Kaynağa Gözat

Add url support, loading animation and informative placeholder

niels 4 yıl önce
ebeveyn
işleme
dc2a5b6a7f

+ 34 - 11
frontend/chuchufe/src/App.js

@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { Fragment, useEffect, useState } from 'react';
 import './css/App.css';
 import './css/fontawesome.css';
 import './css/solid.css';
@@ -7,20 +7,38 @@ import './css/main.css';
 import useRoom from "./util/useRoom";
 import ChooseRoom from "./components/ChooseRoom";
 import Room from "./components/Room";
+import LoadingLogo from "./components/LoadingLogo";
+import NavBar from "./components/NavBar";
 
+function getPathFromUrl() {
+    return new URLSearchParams(window.location.search).get("room") || null
+}
 
-// const PATH = new URLSearchParams(window.location.search).get("room")
-// if (PATH === "" || PATH === undefined || PATH === null) {
-//     window.location = "/";
-// }
-
+function App() {
+    const [path, setPath] = useState(getPathFromUrl());
+    const { room, setRoom, resolver, socket } = useRoom(path);
 
+    useEffect(() => {
+        window.onpopstate = (_) => {
+            setPath(getPathFromUrl());
+        }
+    })
 
-function App() {
-    const [path, setPath] = useState(null);
-    const {room, setRoom, resolver, socket} = useRoom(path);
+    useEffect(() => {
+        if (path === null) {
+            const title = "ChuChube - Choose Room";
+            window.history.pushState({}, title, "/")
+            document.title = title;
+        } else {
+            const title = `ChuChube - ${path}`;
+            window.history.pushState({}, title, `player?room=${path}`)
+            document.title = title;
+        }
+    }, [path])
 
-    if (socket.connected) {
+    if (path === null) {
+        return <ChooseRoom setPath={setPath}/>
+    } else if (socket.connected) {
         return <Room room={room}
                      setRoom={setRoom}
                      exitRoom={() => setPath(null)}
@@ -28,7 +46,12 @@ function App() {
                      resolver={resolver}
         />;
     } else {
-        return <ChooseRoom setPath={setPath}/>
+        return <Fragment>
+            <NavBar exitRoom={() => setPath(null)}/>
+            <div className="absoluteCenter" style={{height: "200px"}}>
+                <LoadingLogo/>
+            </div>
+        </Fragment>
     }
 }
 

+ 12 - 0
frontend/chuchufe/src/components/LoadingLogo.js

@@ -0,0 +1,12 @@
+import React from "react";
+import bg from '../img/icon-bg.svg'
+import train from '../img/icon-train.svg'
+
+export default function LoadingLogo() {
+    return <div className="loadingLogoContainer">
+        <div className="loadingLogoContainingBlock">
+            <img className="loadingLogoBg" src={bg} alt="loading icon"/>
+            <img className="loadingLogo" src={train} alt=""/>
+        </div>
+    </div>
+}

+ 1 - 2
frontend/chuchufe/src/components/SearchResults.js

@@ -1,7 +1,6 @@
 import React from 'react';
 import { ListOperationTypes, MessageTypes, YoutubeResourceType } from "../util/enums";
 import { makeMessage } from "../util/Resolver";
-import useMapBuilder from "../util/useMapBuilder";
 
 function makeSearchResult(item, socket, addVideoInfo) {
     const { id, snippet } = item
@@ -58,7 +57,7 @@ function makeSearchResult(item, socket, addVideoInfo) {
 
 export default function SearchResults({ searchResults, socket, videoInfoMap, setVideoInfoMap }) {
 
-    const addVideoInfo = (k, v) => setVideoInfoMap(new Map(videoInfoMap).set(k,v));
+    const addVideoInfo = (k, v) => setVideoInfoMap(new Map(videoInfoMap).set(k, v));
 
     return <div className="row">
         <div className="list-group col">

+ 5 - 5
frontend/chuchufe/src/components/YoutubePlayer.js

@@ -1,9 +1,6 @@
 import React, { useEffect, useMemo, useRef, useState } from "react";
 import { PlayerState, YoutubePlayerState } from "../util/enums";
 
-const PLAYER_WIDTH = 640
-const PLAYER_HEIGHT = 360
-
 export default function YoutubePlayer({ playback, onSongEnd }) {
     const { song, state } = playback;
     const id = useMemo(() => `youtube-player-${Math.floor(1e15 * Math.random())}`, []);
@@ -131,7 +128,10 @@ export default function YoutubePlayer({ playback, onSongEnd }) {
         <div className="playerContainer" hidden={!playerConnected || song === null}>
             <div id={id}/>
         </div>
-        <div className="playerContainer" hidden={playerConnected && song !== null}
-             style={{ background: "white" }}/>
+        <div className="playerContainer" hidden={playerConnected && song !== null} style={{textAlign: "center"}}>
+            <div className="d-flex justify-content-center playerPlaceholder">
+                <h5 className="text-secondary pt-2">Use the search to add a song to the queue</h5>
+            </div>
+        </div>
     </div>
 }

+ 30 - 0
frontend/chuchufe/src/css/main.css

@@ -27,6 +27,36 @@ input, select, textarea, button {
     left: 20px
 }
 
+@keyframes slidein {
+    from {
+        margin-left: -75%;
+    }
+    to {
+        margin-left: 80%;
+    }
+
+}
+
+.loadingLogo {
+    position: absolute;
+    left: 0;
+    top: 0;
+}
+
+.loadingLogo {
+    animation: 3s linear infinite slidein;
+}
+
+.loadingLogoContainingBlock {
+    position: relative;
+    overflow: hidden;
+    display: inline-block;
+}
+
+.loadingLogoContainer {
+    text-align: center;
+}
+
 .container {
     margin-bottom: 20px;
 }

+ 1 - 1
frontend/chuchufe/src/util/useRoom.js

@@ -37,10 +37,10 @@ export default function useRoom(path) {
         if (path !== null) {
             const ws = resolverRef.current.connectSocket(path);
             ws.addEventListener("open", function () {
+                setConnected(true);
                 ws.send(makeMessage(MessageTypes.STATE, null))
             });
             ws.addEventListener("message", console.log);
-            setConnected(true);
             return (() => {
                 ws.close();
                 setConnected(false);