Большой консолидирующий коммит после поднятия studio.rublox.pro (28 мая 2026). Содержит изменения которые делались в процессе подготовки прод-окружения: Фиксы импортов после выноса из minecraftia: - Массовая замена путей ../../components → ../components (40+ файлов в src/community/, src/admin-preview/) - Замена ../KubikonEditor/ → ../editor/, ../KubikonStudio/ → ../community/, ../AdminPreview/ → ../admin-preview/ - API.js скопирован из минки целиком (было 8 экспортов, стало 312) - Добавлены PLAYER_URL, MyButton_1, недостающие компоненты - Заменены require() на статические ES-imports в BabylonScene, PrimitiveManager, GameRuntime (Vite не поддерживает CJS require) Структура ассетов: - public/kubikon-templates/ → public/assets/kubikon-templates/ - public/kubikon-learn/ → public/assets/kubikon-learn/ - (код искал в /assets/, файлы лежали без /assets/) Навигация роутов внутри студии: - /kubikon-studio/docs → /docs (90+ навигационных вызовов sed-replaced) - /kubikon-editor/X → /edit/X, /kubikon/play/X → /play/X, /kubikon/gd/X → /gd/X UI: - Новый компонент StudioHeader (61px, как в минке) + копия favicon - WithHeader wrapper в App.jsx для всех страниц кроме fullscreen-редактора/плеера - SSO ticket-flow в AuthContext (auto-redeem #ticket= при загрузке) - Тёмная тема карточек игр в ВИКИ (фон #1c2231 вместо #fff, картинка впритык) Документация: - docs/ONBOARDING.md — путь нового контрибьютора от нуля до PR - docs/TUTORIAL_ADD_SCRIPT_API.md — как добавить game.* API - API_USAGE.md — список эндпоинтов backend - README в подпапках engine/, engine/terrain/, engine/voxel/, engine/robloxterrain/, engine/types/ .gitignore: - public/wiki/ исключён (73МБ PNG, будут на CDN отдельной задачей) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
102 lines
6.3 KiB
JavaScript
102 lines
6.3 KiB
JavaScript
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||
import { lazy, Suspense } from 'react';
|
||
import { AuthProvider } from './auth/AuthContext.jsx';
|
||
import { SanctionsProvider } from './auth/SanctionsContext.jsx';
|
||
import LoadingScreen from './LoadingScreen.jsx';
|
||
import StudioHeader from './components/StudioHeader/StudioHeader.jsx';
|
||
|
||
// Обёртка которая показывает StudioHeader над страницей.
|
||
// Не использовать на fullscreen-страницах (редактор, плеер) — там свой UI.
|
||
function WithHeader({ children }) {
|
||
return <><StudioHeader />{children}</>;
|
||
}
|
||
|
||
// Code-splitting: каждая большая страница в своём чанке.
|
||
const KubikonEditor = lazy(() => import('./editor/KubikonEditor.jsx'));
|
||
const KubikonPlayer = lazy(() => import('./preview-player/KubikonPlayer.jsx'));
|
||
const KubikonFeed = lazy(() => import('./community/KubikonFeed.jsx'));
|
||
const KubikonStudio = lazy(() => import('./community/KubikonStudio.jsx'));
|
||
const KubikonDocs = lazy(() => import('./community/KubikonDocs.jsx'));
|
||
const KubikonRules = lazy(() => import('./community/KubikonRules.jsx'));
|
||
const KubikonHeroKit = lazy(() => import('./community/KubikonHeroKit.jsx'));
|
||
const KubikonLearn = lazy(() => import('./community/KubikonLearn.jsx'));
|
||
const KubikonGamePage = lazy(() => import('./community/KubikonGamePage.jsx'));
|
||
const KubikonUserGames = lazy(() => import('./community/KubikonUserGames.jsx'));
|
||
const RealtimeTest = lazy(() => import('./community/RealtimeTest.jsx'));
|
||
|
||
// Geometry Dash sub-app
|
||
const GdShop = lazy(() => import('./gd-shop/GdShop.jsx'));
|
||
const GdMenu = lazy(() => import('./gd-shop/GdMenu.jsx'));
|
||
const GdRules = lazy(() => import('./gd-shop/GdRules.jsx'));
|
||
const GdCoverArt = lazy(() => import('./gd-shop/GdCoverArt.jsx'));
|
||
const GdPlayWrapper = lazy(() => import('./gd-shop/GdPlayWrapper.jsx'));
|
||
|
||
// Превью-роуты для команды дизайнеров (закрытые в проде по роли,
|
||
// в opensource доступны всем — это просто галереи ассетов).
|
||
const GdBossesPreview = lazy(() => import('./admin-preview/GdBossesPreview.jsx'));
|
||
const GdSkinsPreview = lazy(() => import('./admin-preview/GdSkinsPreview.jsx'));
|
||
const GdSpikesPreview = lazy(() => import('./admin-preview/GdSpikesPreview.jsx'));
|
||
const GdArchesPreview = lazy(() => import('./admin-preview/GdArchesPreview.jsx'));
|
||
const GdFinishesPreview = lazy(() => import('./admin-preview/GdFinishesPreview.jsx'));
|
||
const GdPortalsPreview = lazy(() => import('./admin-preview/GdPortalsPreview.jsx'));
|
||
const GdMusicPreview = lazy(() => import('./admin-preview/GdMusicPreview.jsx'));
|
||
const GdSfxPreview = lazy(() => import('./admin-preview/GdSfxPreview.jsx'));
|
||
const GdShipSkinsPreview = lazy(() => import('./admin-preview/GdShipSkinsPreview.jsx'));
|
||
const GdDecoPreview = lazy(() => import('./admin-preview/GdDecoPreview.jsx'));
|
||
|
||
function FallbackLoader() {
|
||
return <LoadingScreen text="Загружаю модуль студии..." />;
|
||
}
|
||
|
||
export default function App() {
|
||
return (
|
||
<BrowserRouter>
|
||
<AuthProvider>
|
||
<SanctionsProvider>
|
||
<Suspense fallback={<FallbackLoader />}>
|
||
<Routes>
|
||
{/* Редактор и плеер (fullscreen) */}
|
||
<Route path="/edit/:id" element={<KubikonEditor />} />
|
||
<Route path="/play/:id" element={<KubikonPlayer />} />
|
||
|
||
{/* Лента, профиль, доки */}
|
||
<Route path="/" element={<WithHeader><KubikonStudio /></WithHeader>} />
|
||
<Route path="/feed" element={<WithHeader><KubikonFeed /></WithHeader>} />
|
||
<Route path="/docs" element={<WithHeader><KubikonDocs /></WithHeader>} />
|
||
<Route path="/rules" element={<WithHeader><KubikonRules /></WithHeader>} />
|
||
<Route path="/hero-kit" element={<WithHeader><KubikonHeroKit /></WithHeader>} />
|
||
<Route path="/learn" element={<WithHeader><KubikonLearn /></WithHeader>} />
|
||
<Route path="/learn/:articleId" element={<WithHeader><KubikonLearn /></WithHeader>} />
|
||
<Route path="/user/:userId" element={<WithHeader><KubikonUserGames /></WithHeader>} />
|
||
<Route path="/realtime-test" element={<WithHeader><RealtimeTest /></WithHeader>} />
|
||
<Route path="/game/:id" element={<WithHeader><KubikonGamePage /></WithHeader>} />
|
||
|
||
{/* Geometry Dash */}
|
||
<Route path="/gd" element={<WithHeader><GdMenu /></WithHeader>} />
|
||
<Route path="/gd/shop" element={<WithHeader><GdShop /></WithHeader>} />
|
||
<Route path="/gd/rules" element={<WithHeader><GdRules /></WithHeader>} />
|
||
<Route path="/gd/cover-art" element={<WithHeader><GdCoverArt /></WithHeader>} />
|
||
<Route path="/gd/play/:id" element={<GdPlayWrapper />} />
|
||
|
||
{/* Каталоги ассетов (для дизайнеров) */}
|
||
<Route path="/preview/gd/bosses" element={<WithHeader><GdBossesPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/skins" element={<WithHeader><GdSkinsPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/spikes" element={<WithHeader><GdSpikesPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/arches" element={<WithHeader><GdArchesPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/finishes" element={<WithHeader><GdFinishesPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/portals" element={<WithHeader><GdPortalsPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/music" element={<WithHeader><GdMusicPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/sfx" element={<WithHeader><GdSfxPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/ship-skins" element={<WithHeader><GdShipSkinsPreview /></WithHeader>} />
|
||
<Route path="/preview/gd/deco" element={<WithHeader><GdDecoPreview /></WithHeader>} />
|
||
|
||
{/* 404 → главная */}
|
||
<Route path="*" element={<WithHeader><KubikonStudio /></WithHeader>} />
|
||
</Routes>
|
||
</Suspense>
|
||
</SanctionsProvider>
|
||
</AuthProvider>
|
||
</BrowserRouter>
|
||
);
|
||
}
|