diff --git a/.env.development b/.env.development index 2542b99..896e5ab 100644 --- a/.env.development +++ b/.env.development @@ -4,5 +4,5 @@ VITE_COORD_URL=https://coord.graff.tech VITE_CRM_API_URL=https://crm.stream.graff.tech/api # VITE_API_URL=http://localhost:5002 VITE_API_URL=https://stream.graff.tech/api -# VITE_SOCKET_URL=http://localhost:5003 -VITE_SOCKET_URL=https://stream.graff.tech \ No newline at end of file +VITE_SOCKET_URL=http://localhost:5003 +# VITE_SOCKET_URL=https://stream.graff.tech \ No newline at end of file diff --git a/src/components/User.tsx b/src/components/User.tsx index db3c88b..36257e8 100644 --- a/src/components/User.tsx +++ b/src/components/User.tsx @@ -9,6 +9,7 @@ import IUser from "../types/IUser"; import CloseIcon from "./icons/CloseIcon"; import { useState } from "react"; import { useClickAway } from "@uidotdev/usehooks"; +import SpinnerIcon from "./icons/SpinnerIcon"; interface Props { me: IUser; @@ -25,16 +26,23 @@ function User({ me, user, handleTransferControl, handleKick }: Props) { }); return ( -
-
-

{user.name[0]?.toUpperCase()}

- {user?.isControlAllowed && ( -
- )} -
-

{user.name}

-
- {isMobile ? : } +
+
+
+

{user.name[0]?.toUpperCase()}

+ {user?.isControlAllowed && ( +
+ )} +
+

{user.name}

+
+ {isMobile ? : } +
+ {!user.isVideoInitialized && }
{me.isAdmin && ( @@ -48,7 +56,7 @@ function User({ me, user, handleTransferControl, handleKick }: Props) { {showMore && ( -
+
{/*
+
+
+ {me && + users.map((user) => { + if (user.id !== me.id) { + return ( + transferControl(user.id)} + handleKick={() => kick(user.id)} + /> + ); + } + })} +
+ {/*
+
+ + setMessageText(e.target.value.replace(/\s+/g, " ")) + } + /> + +
+
*/} +
+ ); +} + +export default Users; diff --git a/src/components/Video.tsx b/src/components/Video.tsx index 226f6e1..6eee6ce 100644 --- a/src/components/Video.tsx +++ b/src/components/Video.tsx @@ -5,6 +5,7 @@ import useIsAudioActive from "use-is-audio-active"; import IUser from "../types/IUser"; import SoundOffIcon from "./icons/SoundOffIcon"; import SoundOnIcon from "./icons/SoundOnIcon"; +import ChevronDownIcon from "./icons/ChevronDownIcon"; interface Props { mediaStream: MediaStream | null; @@ -17,6 +18,7 @@ function Video({ mediaStream, muted, user }: Props) { const isSpeaking = useIsAudioActive({ source: mediaStream }); const [_muted, setMuted] = useState(muted); const [isLoading, setIsLoading] = useState(true); + const [minimized, setMinimized] = useState(user?.isAdmin ? false : true); function toggleSound() { if (!remoteVideoRef.current) return; @@ -44,20 +46,33 @@ function Video({ mediaStream, muted, user }: Props) { }, [remoteVideoRef.current]); return ( -
+
-
-

{user?.name}

- +

{user?.name}

+
+
{isLoading && ( diff --git a/src/components/icons/SpinnerIcon.tsx b/src/components/icons/SpinnerIcon.tsx new file mode 100644 index 0000000..1eda108 --- /dev/null +++ b/src/components/icons/SpinnerIcon.tsx @@ -0,0 +1,66 @@ +function SpinnerIcon() { + return ( + + + + + + + + + + + + + ); +} + +export default SpinnerIcon; diff --git a/src/components/icons/UsersIcon.tsx b/src/components/icons/UsersIcon.tsx new file mode 100644 index 0000000..840ef53 --- /dev/null +++ b/src/components/icons/UsersIcon.tsx @@ -0,0 +1,31 @@ +interface Props { + className?: string; +} + +function UsersIcon({ className = "" }: Props) { + return ( + + + + + ); +} + +export default UsersIcon; diff --git a/src/pages/StreamPage.tsx b/src/pages/StreamPage.tsx index 91a3d2c..105af6c 100644 --- a/src/pages/StreamPage.tsx +++ b/src/pages/StreamPage.tsx @@ -43,7 +43,8 @@ import DesktopIcon from "../components/icons/DesktopIcon"; import MobileIcon from "../components/icons/MobileIcon"; import ChatIcon from "../components/icons/ChatIcon"; import useChatStore from "../stores/useChatStore"; -import User from "../components/User"; +import UsersIcon from "../components/icons/UsersIcon"; +import Users from "../components/Users"; // import ChatIcon from "../components/icons/ChatIcon"; // import MoreIcon from "../components/icons/MoreIcon"; @@ -83,6 +84,7 @@ function StreamPage() { const [isVideoInitialized, setIsVideoInitialized] = useState(false); const [step, setStep] = useState(1); const [isShowChat, setIsShowChat] = useState(false); + const [isShowUsers, setIsShowUsers] = useState(false); const { isPortrait } = useMobileOrientation(); const { setMessages } = useChatStore(); @@ -184,6 +186,7 @@ function StreamPage() { name, peerId, superAdmin, + isVideoInitialized, }, }, }); @@ -245,6 +248,7 @@ function StreamPage() { if (!permission) return; setIsMicEnabled(track.enabled); + socket?.emit("mic-enabled", track.enabled); }); } @@ -308,6 +312,10 @@ function StreamPage() { socket?.emit("kick", userId); } + function videoInitialized() { + socket?.emit("video-initialized", userId); + } + async function getActiveSession() { const activeSession: any = await api .get(`activeSessions/${params.id}`) @@ -350,6 +358,7 @@ function StreamPage() { if (!isVideoInitialized) { setModal(); } else { + videoInitialized(); setModal(null); } }, [step, isVideoInitialized]); @@ -399,7 +408,7 @@ function StreamPage() { className="hidden pointer-events-none lg:block" />
-
+

@@ -485,8 +494,33 @@ function StreamPage() { )}

-
- {me && +
+
+
+ {/* {me && users.map((user) => { if (user.id !== userId) { return ( @@ -500,7 +534,7 @@ function StreamPage() { /> ); } - })} + })} */}
@@ -509,7 +543,9 @@ function StreamPage() { variant="secondary" icon={} onlyIcon - onClick={() => setIsShowChat((prev) => !prev)} + onClick={() => ( + setIsShowChat((prev) => !prev), setIsShowUsers(false) + )} />
-
+
-

{name}

+

+ {name} +

{remoteStreams.map(({ peerId, mediaStream }) => ( @@ -611,6 +654,13 @@ function StreamPage() {
{isShowChat && setIsShowChat(false)} />} + {isShowUsers && ( + setIsShowUsers(false)} + transferControl={(userId) => transferControl(userId)} + kick={(userId) => kick(userId)} + /> + )} {isPortrait && (
diff --git a/src/types/IUser.ts b/src/types/IUser.ts index b889ef5..3ae45f9 100644 --- a/src/types/IUser.ts +++ b/src/types/IUser.ts @@ -6,6 +6,8 @@ interface IUser { isControlAllowed: boolean; isMicAllowed: boolean; peerId: string; + micEnabled: boolean; + isVideoInitialized: boolean; } export default IUser;