player/src/App.jsx
МИН 6d86aa7c36 docs: переводы оставшихся английских комментариев на русский
- src/api/API.js — комменты, описание env
- vite.config.js — описание полей
- src/App.jsx — IndexRoute (текст «Плеер Рублокса»)
- src/KubikonPlayer/KubikonPlayer.jsx — exitPlayer
- src/engine/PlayerController.js — _storysApiUrl
- src/engine/GameRuntime.js — _resolveExternalUrl
- src/engine/devlog.js — убрал упоминания приватных путей разработчика
- src/fixtures/sample-game.json — title/description
2026-05-27 23:18:38 +03:00

92 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Этап 2: полный flow авторизации через ticket.
//
// Route /:id — единственный полезный, обработка отсутствия gameId через
// "*" (показываем LoadingScreen с сообщением).
//
// Цепочка состояний:
// 1. PlayerAuthProvider грузит JWT/ticket → isLoading=true
// 2. isLoading=false, error='no_jwt_local' (только localhost) → подсказка
// про DevTools
// 3. isAuthenticated=true → рендерим KubikonPlayer
// 4. Любая redeem-ошибка → "Сессия истекла. Вернись на rublox.pro" с
// кнопкой возврата
//
// На проде (player.rublox.pro) шаг 2 не наступает — там redirect на
// rublox.pro/app сразу.
import { BrowserRouter, Routes, Route, useParams } from 'react-router-dom';
import { PlayerAuthProvider, useAuth } from './auth/PlayerAuth';
import KubikonPlayer from './KubikonPlayer/KubikonPlayer';
import LoadingScreen from './LoadingScreen';
import { RUBLOX_HOME } from './api/API';
// Подфаза 3.4 RUBLOX_ACCESSORY_ATTACHMENT_PLAN.md
import PreviewSkinRoute from './PreviewSkin/PreviewSkinRoute';
// Фаза 5.6 RUBLOX_DESIGNER_PLAN.md — preview модели
import PreviewModelRoute from './PreviewSkin/PreviewModelRoute';
// 2026-05-27 — preview аватара
import PreviewAvatarRoute from './PreviewSkin/PreviewAvatarRoute';
// 6.7 RUBLOX_DESIGNER_PLAN.md — preview emote-анимации
import PreviewEmoteRoute from './PreviewSkin/PreviewEmoteRoute';
function PlayerRoute() {
const { id } = useParams();
const { isAuthenticated, isLoading, error } = useAuth();
if (isLoading) return <LoadingScreen text="Подключение" />;
if (error === 'no_jwt_local') {
return (
<LoadingScreen
text="Нужен JWT"
subText={`Положи токен в localStorage["player_jwt"] и перезагрузи страницу. Это dev-fallback, на проде такого экрана нет — там сразу редирект на rublox.pro. (gameId=${id})`}
/>
);
}
if (!isAuthenticated) {
return (
<LoadingScreen
text="Сессия истекла"
subText="Вернись на rublox.pro и попробуй ещё раз."
/>
);
}
return <KubikonPlayer />;
}
function IndexRoute() {
// Прямой заход на `/` без gameId.
// На реальном деплое юзер должен прийти с ticket'ом — редиректим обратно
// на главный сайт. На dev (localhost) показываем подсказку.
if (typeof window !== 'undefined' && window.location.hostname !== 'localhost'
&& window.location.hostname !== '127.0.0.1') {
window.location.assign(RUBLOX_HOME);
return null;
}
return <LoadingScreen text="Плеер Рублокса" subText="Открой /<gameId> чтобы запустить игру." />;
}
export default function App() {
return (
<PlayerAuthProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<IndexRoute />} />
{/* Preview-режим для дизайнеров (Подфаза 3.4) — должен быть ДО /:id,
иначе React Router примет '_preview-skin' за gameId. */}
<Route path="/_preview-skin/:itemId" element={<PreviewSkinRoute />} />
{/* Preview модели (Фаза 5.6 DESIGNER_PLAN) — пустой мир с моделью */}
<Route path="/_preview-model/:itemId" element={<PreviewModelRoute />} />
{/* Preview аватара — пустой мир + персонаж с этим телом */}
<Route path="/_preview-avatar/:itemId" element={<PreviewAvatarRoute />} />
{/* Preview emote — пустой мир + бекон с проигрыванием анимации */}
<Route path="/_preview-emote/:itemId" element={<PreviewEmoteRoute />} />
<Route path="/:id" element={<PlayerRoute />} />
<Route path="*" element={<LoadingScreen text="Игра не найдена" />} />
</Routes>
</BrowserRouter>
</PlayerAuthProvider>
);
}