// Этап 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 ; if (error === 'no_jwt_local') { return ( ); } if (!isAuthenticated) { return ( ); } return ; } 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 ; } export default function App() { return ( } /> {/* Preview-режим для дизайнеров (Подфаза 3.4) — должен быть ДО /:id, иначе React Router примет '_preview-skin' за gameId. */} } /> {/* Preview модели (Фаза 5.6 DESIGNER_PLAN) — пустой мир с моделью */} } /> {/* Preview аватара — пустой мир + персонаж с этим телом */} } /> {/* Preview emote — пустой мир + бекон с проигрыванием анимации */} } /> } /> } /> ); }