// Этап 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 — пустой мир + бекон с проигрыванием анимации */}
} />
} />
} />
);
}