This commit is contained in:
2024-02-06 13:20:47 +05:00
parent 4e5e013c97
commit 42f07f410e
7 changed files with 1041 additions and 829 deletions
+3 -3
View File
@@ -15,8 +15,8 @@
"@livekit/components-styles": "^1.0.6",
"@uidotdev/usehooks": "^2.0.1",
"date-fns": "^2.30.0",
"i18next": "^22.5.0",
"i18next-browser-languagedetector": "^7.0.2",
"i18next": "^23.8.2",
"i18next-browser-languagedetector": "^7.2.0",
"ky": "^1.1.3",
"livekit-client": "^1.13.2",
"react": "^18.2.0",
@@ -25,7 +25,7 @@
"react-device-detect": "^2.2.3",
"react-dom": "^18.2.0",
"react-full-screen": "^1.1.1",
"react-i18next": "^12.3.1",
"react-i18next": "^14.0.3",
"react-input-mask": "^2.0.4",
"react-qr-code": "^2.0.11",
"react-router-dom": "^6.11.2",
+29 -13
View File
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import ky from "ky";
import { useEffect, useState } from "react";
import { parseUserAgent } from "react-device-detect";
function HistoryPage() {
const [history, setHistory] = useState([]);
@@ -20,19 +21,34 @@ function HistoryPage() {
return (
<div className="text-[#F2F2F2] space-y-4 p-4">
<p>Всего сессий: {history.length}</p>
{history.map((item: any) => (
<div key={item.id} className="p-4 rounded-lg bg-[#22222A]">
<p>
Дата и время: {new Date(item.createdAt).toLocaleString()}
</p>
<p>Сборка: "{item.build}"</p>
<p>Локация: "{item.location}"</p>
<p>Сервер: "{item.server}"</p>
<p>IP клиента: {item.ownerIp}</p>
{/* <p>Город: {item.city}</p> */}
{/* <p>Устройство: {item.headers["user-agent"]}</p> */}
</div>
))}
{history.map(
(item: any) =>
item.city &&
item.headers && (
<div key={item.id} className="p-4 rounded-lg bg-[#22222A]">
<p>
Дата и время: <b>{new Date(item.createdAt).toLocaleString()}</b>
</p>
<p>
Сборка: <b>{item.title}</b>
</p>
<p>
Город: <b>{item.city}</b>
</p>
<p>
Устройство:{" "}
<b>
{parseUserAgent(item.headers["user-agent"]).os.name}{" "}
{parseUserAgent(item.headers["user-agent"]).os.version} (
{parseUserAgent(item.headers["user-agent"]).browser.name})
</b>
</p>
<p>Локация: {item.location}</p>
<p>Сервер: {item.server}</p>
<p>IP клиента: {item.headers["x-forwarded-for"]}</p>
</div>
)
)}
</div>
);
}
+1 -1
View File
@@ -53,7 +53,7 @@ function ScheduledPage() {
<p className="text-2xl font-gilroy">Сеанс начнется через:</p>
<p className="text-6xl font-gilroy">
<Countdown
date={Date.now() + countdownSeconds + 10000}
date={Date.now() + countdownSeconds + 15000}
onComplete={() => window.location.reload()}
/>
</p>
+24 -1
View File
@@ -35,6 +35,7 @@ import { differenceInMilliseconds, format, parseISO } from "date-fns";
import HandOnIcon from "./components/icons/HandOnIcon";
import { useMobileOrientation } from "react-device-detect";
import RotateDeviceIcon from "./components/icons/RotateDeviceIcon";
import LoaderIcon from "./components/icons/LoaderIcon";
function StreamPage() {
const { t } = useTranslation();
@@ -161,6 +162,25 @@ function StreamPage() {
});
}
async function checkIsActiveSession() {
const activeSession: any = await ky
.get(`${import.meta.env.VITE_COORD_URL}/active_sessions/${params.id}`)
.json();
console.log(activeSession);
if (!activeSession) {
setIsStreamEnded(true);
return;
}
if (!isStreamEnded) {
setTimeout(() => {
checkIsActiveSession();
}, 1000);
}
}
useEffect(() => {
connect();
@@ -206,6 +226,8 @@ function StreamPage() {
}
});
checkIsActiveSession();
return () => {
socket.off("connect");
socket.off("join");
@@ -249,7 +271,8 @@ function StreamPage() {
)}
</>
) : (
<div className="absolute top-0 left-0 w-full h-full flex justify-center items-center">
<div className="absolute top-0 left-0 w-full h-full flex justify-center items-center gap-4">
<LoaderIcon className="animate-spin w-8 h-8" />
<Trans i18nKey="streamWaiting">Ожидание потока</Trans>
</div>
)
+11 -1
View File
@@ -8,6 +8,7 @@ import {
PixelStreaming,
} from "@epicgames-ps/lib-pixelstreamingfrontend-ue5.3";
import { Trans } from "react-i18next";
import LoaderIcon from "./icons/LoaderIcon";
export interface PixelStreamingWrapperProps {
initialSettings?: Partial<AllSettings>;
@@ -25,6 +26,8 @@ export const PixelStreamingWrapper = ({
// A boolean state variable that determines if the Click to play overlay is shown:
const [clickToPlayVisible, setClickToPlayVisible] = useState<boolean>(false);
const [videoInitialized, setVideoInitialized] = useState<boolean>(false);
const videoInitializedRef = useRef<boolean>();
videoInitializedRef.current = videoInitialized;
// Run on component mount:
useEffect(() => {
@@ -50,6 +53,12 @@ export const PixelStreamingWrapper = ({
document.getElementById("hiddenInput")?.remove();
document.getElementById("editTextButton")?.remove();
setTimeout(() => {
if (!videoInitializedRef.current) {
window.location.reload();
}
}, 10000);
// Clean up on component unmount:
return () => {
try {
@@ -65,7 +74,8 @@ export const PixelStreamingWrapper = ({
<div className="relative w-screen h-screen">
<div className="w-full h-[100svh]" ref={videoParent} />
{!videoInitialized && (
<div className="absolute top-0 left-0 w-full h-full flex justify-center items-center">
<div className="absolute top-0 left-0 w-full h-full flex justify-center items-center gap-4">
<LoaderIcon className="animate-spin w-8 h-8" />
<Trans i18nKey="streamBuffering">Буферизация потока</Trans>
</div>
)}
+8 -6
View File
@@ -1,6 +1,6 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import detector from "i18next-browser-languagedetector";
import LanguageDetector from "i18next-browser-languagedetector";
// the translations
// (tip move them in a JSON file and import them,
@@ -237,15 +237,17 @@ const resources = {
};
void i18n
.use(detector)
.use(initReactI18next) // passes i18n down to react-i18next
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources,
fallbackLng: ["ru"],
fallbackLng: "ru",
interpolation: {
escapeValue: false, // react already safes from xss
escapeValue: false,
},
// debug: true,
// detection: {
// caches: [],
// },
});
export default i18n;
+965 -804
View File
File diff suppressed because it is too large Load Diff