upd
This commit is contained in:
+83
-201
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-irregular-whitespace */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
||||
@@ -9,7 +10,7 @@ import { io } from "socket.io-client";
|
||||
import userAgentParser from "ua-parser-js";
|
||||
import { Player } from "./components/Player";
|
||||
import { Trans } from "react-i18next";
|
||||
import { useScreen } from "usehooks-ts";
|
||||
// import { useScreen } from "usehooks-ts";
|
||||
import ShareIcon from "./components/icons/ShareIcon";
|
||||
import ModalContainer from "./components/ModalContainer";
|
||||
import useModalStore from "./stores/useModalStore";
|
||||
@@ -20,14 +21,9 @@ import "react-toastify/dist/ReactToastify.css";
|
||||
import FullscreenIcon from "./components/icons/FullscreenIcon";
|
||||
import WindowedModeIcon from "./components/icons/WindowedModeIcon";
|
||||
import QRIcon from "./components/icons/QRIcon";
|
||||
import AdminUserIcon from "./components/icons/AdminUserIcon";
|
||||
import UserIcon from "./components/icons/UserIcon";
|
||||
import MobilePhoneIcon from "./components/icons/MobilePhoneIcon";
|
||||
import DesktopIcon from "./components/icons/DesktopIcon";
|
||||
import HandOffIcon from "./components/icons/HandOffIcon";
|
||||
import HandOnIcon from "./components/icons/HandOnIcon";
|
||||
import ExitIcon from "./components/icons/ExitIcon";
|
||||
import QRCodeModal from "./components/modals/QRCodeModal";
|
||||
import PersonsIcon from "./components/icons/PersonsIcon";
|
||||
import UsersManagementModal from "./components/modals/UsersManagementModal";
|
||||
|
||||
function StreamPage() {
|
||||
const params = useParams();
|
||||
@@ -38,18 +34,18 @@ function StreamPage() {
|
||||
const [socket, setSocket] = useState<any>(null);
|
||||
const [users, setUsers] = useState<any>([]);
|
||||
const [me, setMe] = useState<any>({});
|
||||
const [isOpenSidebar, setIsOpenSidebar] = useState<boolean>(false);
|
||||
const screen = useScreen();
|
||||
|
||||
// const screen = useScreen();
|
||||
const [modal, setModal] = useModalStore((state) => [
|
||||
state.modal,
|
||||
state.setModal,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (screen?.orientation.type.includes("portrait")) {
|
||||
// alert("portrait");
|
||||
}
|
||||
}, [screen]);
|
||||
// useEffect(() => {
|
||||
// if (screen?.orientation.type.includes("portrait")) {
|
||||
// alert("portrait");
|
||||
// }
|
||||
// }, [screen]);
|
||||
|
||||
function toastWarn(text: string) {
|
||||
toast.warn(text, {
|
||||
@@ -116,6 +112,8 @@ function StreamPage() {
|
||||
socket.on("join", (_socketId, room) => {
|
||||
setUsers(room.users);
|
||||
// console.log("join: ", _socketId, room.users);
|
||||
|
||||
toastInfo("Присоеденился новый участник");
|
||||
});
|
||||
|
||||
socket.on("update", (_socketId, room) => {
|
||||
@@ -147,192 +145,7 @@ function StreamPage() {
|
||||
}, [me]);
|
||||
|
||||
return (
|
||||
<FullScreen handle={handleFullScreen} className="h-screen text-[#F2F2F2] ">
|
||||
<div
|
||||
className={[
|
||||
"absolute z-30 top-0 left-0 h-screen bg-[#1C1D21] space-y-2 flex flex-col justify-between text-xs whitespace-nowrap text-clip transition-all",
|
||||
isOpenSidebar ? "w-[280px]" : "w-0",
|
||||
].join(" ")}
|
||||
>
|
||||
<div
|
||||
className={[
|
||||
"p-2 transition-opacity",
|
||||
isOpenSidebar ? "opacity-100" : "opacity-0",
|
||||
].join(" ")}
|
||||
>
|
||||
<div className="flex flex-col overflow-hidden">
|
||||
{!handleFullScreen.active ? (
|
||||
<button
|
||||
onClick={handleFullScreen.enter}
|
||||
className="p-2 flex space-x-2 items-center outline-none"
|
||||
>
|
||||
<FullscreenIcon />
|
||||
<span>
|
||||
<Trans i18nKey={"fullscreenMode"}>Полноэкранный режим</Trans>
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={handleFullScreen.exit}
|
||||
className="p-2 flex space-x-2 items-center outline-none"
|
||||
>
|
||||
<WindowedModeIcon />
|
||||
<span>
|
||||
<Trans i18nKey={"windowedMode"}>Оконный режим</Trans>
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={() => setModal(<QRCodeModal />)}
|
||||
className="p-2 flex space-x-2 items-center outline-none"
|
||||
>
|
||||
<QRIcon />
|
||||
<span>
|
||||
<Trans i18nKey={"inviteByQR"}>Пригласить по QR</Trans>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setModal(<ShareModal />)}
|
||||
className="p-2 flex space-x-2 items-center outline-none"
|
||||
>
|
||||
<ShareIcon />
|
||||
<span>Поделиться</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="m-1 h-0.5 bg-[#2E3038]"></div>
|
||||
|
||||
<div className="">
|
||||
{users.map((user: any) => (
|
||||
<div
|
||||
key={user.id}
|
||||
className="p-2 border-gray-700 flex items-center space-x-2"
|
||||
>
|
||||
<div className="flex flex-col justify-center items-center">
|
||||
{user.admin ? <AdminUserIcon /> : <UserIcon />}
|
||||
|
||||
{me && me.id === user.id && (
|
||||
<p className="text-[#73788C]">Вы</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="font-bold">
|
||||
{user.admin ? "Администратор" : "Пользователь"}
|
||||
</p>
|
||||
<p>({user.city})</p>
|
||||
</div>
|
||||
|
||||
{new userAgentParser(user.ua).getDevice().type === "mobile" ? (
|
||||
<MobilePhoneIcon />
|
||||
) : (
|
||||
<DesktopIcon />
|
||||
)}
|
||||
|
||||
{!user.admin && (
|
||||
<>
|
||||
{user.allowControl ? (
|
||||
<button
|
||||
onClick={() => update(user.id, { allowControl: false })}
|
||||
className="outline-none mt-1"
|
||||
>
|
||||
<HandOnIcon />
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => update(user.id, { allowControl: true })}
|
||||
className="outline-none mt-1"
|
||||
>
|
||||
<HandOffIcon />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{me && me.admin && !user.admin && (
|
||||
<button
|
||||
onClick={() => kick(user.id)}
|
||||
className="outline-none"
|
||||
>
|
||||
<ExitIcon />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute top-[50%] -right-[29px] -translate-y-[50%] transition-all">
|
||||
{!isOpenSidebar ? (
|
||||
<button
|
||||
onClick={() => setIsOpenSidebar(true)}
|
||||
className="p-2 relative outline-none"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="130"
|
||||
viewBox="0 0 24 130"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 1H3.69231L22.4433 30.547C23.4601 32.1492 24 34.0076 24 35.9053V94.0947C24 95.9924 23.4601 97.8508 22.4433 99.453L3.69231 129H0V1Z"
|
||||
fill="#1C1D21"
|
||||
/>
|
||||
<path
|
||||
d="M13 70L18 65L13 60"
|
||||
stroke="#C5C7CE"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M8 75L8 65L8 55"
|
||||
stroke="#C5C7CE"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => setIsOpenSidebar(false)}
|
||||
className="p-2 outline-none"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="130"
|
||||
viewBox="0 0 24 130"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0 1H3.69231L22.4433 30.547C23.4601 32.1492 24 34.0076 24 35.9053V94.0947C24 95.9924 23.4601 97.8508 22.4433 99.453L3.69231 129H0V1Z"
|
||||
fill="#1C1D21"
|
||||
/>
|
||||
<path
|
||||
d="M11 70L6 65L11 60"
|
||||
stroke="#C5C7CE"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M16 75L16 65L16 55"
|
||||
stroke="#C5C7CE"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FullScreen handle={handleFullScreen} className="h-screen text-[#F2F2F2]">
|
||||
{!isStreamEnded ? (
|
||||
isStreamLoaded ? (
|
||||
<>{streamUrl && <Player ss={streamUrl} />}</>
|
||||
@@ -369,6 +182,75 @@ function StreamPage() {
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="absolute top-0 left-0 min-h-screen flex flex-col justify-center transition-all">
|
||||
<div className="flex flex-col gap-2 lg:p-4 p-2">
|
||||
{new userAgentParser().getDevice().model !== "iPhone" && (
|
||||
<>
|
||||
{!handleFullScreen.active ? (
|
||||
<button
|
||||
onClick={() => handleFullScreen.enter()}
|
||||
className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
|
||||
>
|
||||
<FullscreenIcon />
|
||||
<span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
|
||||
Полноэкранный режим
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => handleFullScreen.exit()}
|
||||
className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
|
||||
>
|
||||
<WindowedModeIcon />
|
||||
<span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
|
||||
Оконный режим
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={() => setModal(<QRCodeModal />)}
|
||||
className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
|
||||
>
|
||||
<QRIcon />
|
||||
<span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
|
||||
Пригласить по QR
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setModal(<ShareModal />)}
|
||||
className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
|
||||
>
|
||||
<ShareIcon />
|
||||
<span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
|
||||
Пригласить по ссылке
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() =>
|
||||
setModal(
|
||||
<UsersManagementModal
|
||||
users={users}
|
||||
me={me}
|
||||
handleUpdate={(socketId, params) => update(socketId, params)}
|
||||
handleKick={(socketId) => kick(socketId)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
|
||||
>
|
||||
<PersonsIcon />
|
||||
<span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
|
||||
Участники
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Transition
|
||||
in={modal ? true : false}
|
||||
timeout={200}
|
||||
|
||||
Reference in New Issue
Block a user