Files
cinny/src/app/pages/Router.tsx
T
Lotus Bot 93e9e11146
CI / Build & Quality Checks (push) Failing after 5m2s
fix: reduce ESLint errors and npm audit vulnerabilities
ESLint (476 → 187 errors):
- Fix import/first: move React.lazy() declarations after all imports in RoomInput.tsx and Router.tsx
- Disable react-hooks v7 React Compiler rules (refs, set-state-in-effect, immutability, purity, use-memo, react-compiler) - not using React Compiler yet
- Add eslint-disable for lotus-terminal.css.ts (no-explicit-any in CSS-in-JS)
- Add eslint-disable for cryptE2ERoomKeys.js (intentional bitwise crypto ops)
- Auto-fix 17 remaining fixable errors

npm audit (14 → 11 vulns, 5 → 3 HIGH in prod):
- Upgrade @giphy/react-components 5.9.4 → 10.1.2, js-fetch-api → 5.8.0, js-types → 5.1.0
- Add npm overrides to force dompurify >=3.3.4 and uuid >=11.1.1 in @giphy/js-util
- CI audit now uses --omit=dev to exclude devDep transitive vulns (lodash in commitizen)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 12:08:50 -04:00

415 lines
13 KiB
TypeScript

import React from 'react';
import {
Outlet,
Route,
createBrowserRouter,
createHashRouter,
createRoutesFromElements,
redirect,
} from 'react-router-dom';
import { RoomSkeleton } from '../components/RoomSkeleton';
import { ClientConfig } from '../hooks/useClientConfig';
import {
DIRECT_PATH,
EXPLORE_PATH,
HOME_PATH,
LOGIN_PATH,
INBOX_PATH,
REGISTER_PATH,
RESET_PASSWORD_PATH,
SPACE_PATH,
_CREATE_PATH,
_FEATURED_PATH,
_INVITES_PATH,
_JOIN_PATH,
_LOBBY_PATH,
_NOTIFICATIONS_PATH,
_ROOM_PATH,
_SEARCH_PATH,
_SERVER_PATH,
CREATE_PATH,
} from './paths';
import {
getAppPathFromHref,
getExploreFeaturedPath,
getHomePath,
getInboxNotificationsPath,
getLoginPath,
getOriginBaseUrl,
getSpaceLobbyPath,
} from './pathUtils';
import { ClientBindAtoms, ClientLayout, ClientRoot } from './client';
import { Home, HomeRouteRoomProvider, HomeSearch } from './client/home';
import { Direct, DirectCreate, DirectRouteRoomProvider } from './client/direct';
import { RouteSpaceProvider, Space, SpaceRouteRoomProvider, SpaceSearch } from './client/space';
import { setAfterLoginRedirectPath } from './afterLoginRedirectPath';
import { WelcomePage } from './client/WelcomePage';
import { SidebarNav } from './client/SidebarNav';
import { PageRoot } from '../components/page';
import { ScreenSize } from '../hooks/useScreenSize';
import { MobileFriendlyPageNav, MobileFriendlyClientNav } from './MobileFriendly';
import { ClientInitStorageAtom } from './client/ClientInitStorageAtom';
import { ClientNonUIFeatures } from './client/ClientNonUIFeatures';
import { AuthRouteThemeManager, UnAuthRouteThemeManager } from './ThemeManager';
import { ReceiveSelfDeviceVerification } from '../components/DeviceVerification';
import { AutoRestoreBackupOnVerification } from '../components/BackupRestore';
import { ClientRoomsNotificationPreferences } from './client/ClientRoomsNotificationPreferences';
import { UserRoomProfileRenderer } from '../components/UserRoomProfileRenderer';
import { HomeCreateRoom } from './client/home/CreateRoom';
import { Create } from './client/create';
import { getFallbackSession } from '../state/sessions';
import { CallStatusRenderer } from './CallStatusRenderer';
import { CallEmbedProvider } from '../components/CallEmbedProvider';
const AuthLayout = React.lazy(() => import('./auth').then((m) => ({ default: m.AuthLayout })));
const Login = React.lazy(() => import('./auth').then((m) => ({ default: m.Login })));
const Register = React.lazy(() => import('./auth').then((m) => ({ default: m.Register })));
const ResetPassword = React.lazy(() =>
import('./auth').then((m) => ({ default: m.ResetPassword })),
);
const Room = React.lazy(() => import('../features/room').then((m) => ({ default: m.Room })));
const RoomSettingsRenderer = React.lazy(() =>
import('../features/room-settings').then((m) => ({ default: m.RoomSettingsRenderer })),
);
const SpaceSettingsRenderer = React.lazy(() =>
import('../features/space-settings').then((m) => ({ default: m.SpaceSettingsRenderer })),
);
const CreateRoomModalRenderer = React.lazy(() =>
import('../features/create-room').then((m) => ({ default: m.CreateRoomModalRenderer })),
);
const CreateSpaceModalRenderer = React.lazy(() =>
import('../features/create-space').then((m) => ({ default: m.CreateSpaceModalRenderer })),
);
const SearchModalRenderer = React.lazy(() =>
import('../features/search').then((m) => ({ default: m.SearchModalRenderer })),
);
const Explore = React.lazy(() => import('./client/explore').then((m) => ({ default: m.Explore })));
const FeaturedRooms = React.lazy(() =>
import('./client/explore').then((m) => ({ default: m.FeaturedRooms })),
);
const PublicRooms = React.lazy(() =>
import('./client/explore').then((m) => ({ default: m.PublicRooms })),
);
const Notifications = React.lazy(() =>
import('./client/inbox').then((m) => ({ default: m.Notifications })),
);
const Inbox = React.lazy(() => import('./client/inbox').then((m) => ({ default: m.Inbox })));
const Invites = React.lazy(() => import('./client/inbox').then((m) => ({ default: m.Invites })));
const Lobby = React.lazy(() => import('../features/lobby').then((m) => ({ default: m.Lobby })));
export const createRouter = (clientConfig: ClientConfig, screenSize: ScreenSize) => {
const { hashRouter } = clientConfig;
const mobile = screenSize === ScreenSize.Mobile;
const routes = createRoutesFromElements(
<Route hydrateFallbackElement={null}>
<Route
index
loader={() => {
if (getFallbackSession()) return redirect(getHomePath());
const afterLoginPath = getAppPathFromHref(getOriginBaseUrl(), window.location.href);
if (afterLoginPath) setAfterLoginRedirectPath(afterLoginPath);
return redirect(getLoginPath());
}}
/>
<Route
loader={() => {
if (getFallbackSession()) {
return redirect(getHomePath());
}
return null;
}}
element={
<React.Suspense fallback={null}>
<AuthLayout />
<UnAuthRouteThemeManager />
</React.Suspense>
}
>
<Route
path={LOGIN_PATH}
element={
<React.Suspense fallback={null}>
<Login />
</React.Suspense>
}
/>
<Route
path={REGISTER_PATH}
element={
<React.Suspense fallback={null}>
<Register />
</React.Suspense>
}
/>
<Route
path={RESET_PASSWORD_PATH}
element={
<React.Suspense fallback={null}>
<ResetPassword />
</React.Suspense>
}
/>
</Route>
<Route
loader={() => {
const session = getFallbackSession();
if (!session) {
const afterLoginPath = getAppPathFromHref(
getOriginBaseUrl(hashRouter),
window.location.href,
);
if (afterLoginPath) setAfterLoginRedirectPath(afterLoginPath);
return redirect(getLoginPath());
}
return null;
}}
element={
<AuthRouteThemeManager>
<ClientRoot>
<ClientInitStorageAtom>
<ClientRoomsNotificationPreferences>
<ClientBindAtoms>
<ClientNonUIFeatures>
<CallEmbedProvider>
<ClientLayout
nav={
<MobileFriendlyClientNav>
<SidebarNav />
</MobileFriendlyClientNav>
}
>
<Outlet />
</ClientLayout>
<CallStatusRenderer />
</CallEmbedProvider>
<React.Suspense fallback={null}>
<SearchModalRenderer />
</React.Suspense>
<UserRoomProfileRenderer />
<React.Suspense fallback={null}>
<CreateRoomModalRenderer />
</React.Suspense>
<React.Suspense fallback={null}>
<CreateSpaceModalRenderer />
</React.Suspense>
<React.Suspense fallback={null}>
<RoomSettingsRenderer />
</React.Suspense>
<React.Suspense fallback={null}>
<SpaceSettingsRenderer />
</React.Suspense>
<ReceiveSelfDeviceVerification />
<AutoRestoreBackupOnVerification />
</ClientNonUIFeatures>
</ClientBindAtoms>
</ClientRoomsNotificationPreferences>
</ClientInitStorageAtom>
</ClientRoot>
</AuthRouteThemeManager>
}
>
<Route
path={HOME_PATH}
element={
<PageRoot
nav={
<MobileFriendlyPageNav path={HOME_PATH}>
<Home />
</MobileFriendlyPageNav>
}
>
<Outlet />
</PageRoot>
}
>
{mobile ? null : <Route index element={<WelcomePage />} />}
<Route path={_CREATE_PATH} element={<HomeCreateRoom />} />
<Route path={_JOIN_PATH} element={<p>join</p>} />
<Route path={_SEARCH_PATH} element={<HomeSearch />} />
<Route
path={_ROOM_PATH}
element={
<HomeRouteRoomProvider>
<React.Suspense fallback={<RoomSkeleton />}>
<Room />
</React.Suspense>
</HomeRouteRoomProvider>
}
/>
</Route>
<Route
path={DIRECT_PATH}
element={
<PageRoot
nav={
<MobileFriendlyPageNav path={DIRECT_PATH}>
<Direct />
</MobileFriendlyPageNav>
}
>
<Outlet />
</PageRoot>
}
>
{mobile ? null : <Route index element={<WelcomePage />} />}
<Route path={_CREATE_PATH} element={<DirectCreate />} />
<Route
path={_ROOM_PATH}
element={
<DirectRouteRoomProvider>
<React.Suspense fallback={<RoomSkeleton />}>
<Room />
</React.Suspense>
</DirectRouteRoomProvider>
}
/>
</Route>
<Route
path={SPACE_PATH}
element={
<RouteSpaceProvider>
<PageRoot
nav={
<MobileFriendlyPageNav path={SPACE_PATH}>
<Space />
</MobileFriendlyPageNav>
}
>
<Outlet />
</PageRoot>
</RouteSpaceProvider>
}
>
{mobile ? null : (
<Route
index
loader={({ params }) => {
const { spaceIdOrAlias } = params;
if (spaceIdOrAlias) {
return redirect(getSpaceLobbyPath(spaceIdOrAlias));
}
return null;
}}
element={<WelcomePage />}
/>
)}
<Route
path={_LOBBY_PATH}
element={
<React.Suspense fallback={null}>
<Lobby />
</React.Suspense>
}
/>
<Route path={_SEARCH_PATH} element={<SpaceSearch />} />
<Route
path={_ROOM_PATH}
element={
<SpaceRouteRoomProvider>
<React.Suspense fallback={<RoomSkeleton />}>
<Room />
</React.Suspense>
</SpaceRouteRoomProvider>
}
/>
</Route>
<Route
path={EXPLORE_PATH}
element={
<PageRoot
nav={
<MobileFriendlyPageNav path={EXPLORE_PATH}>
<React.Suspense fallback={null}>
<Explore />
</React.Suspense>
</MobileFriendlyPageNav>
}
>
<Outlet />
</PageRoot>
}
>
{mobile ? null : (
<Route
index
loader={() => redirect(getExploreFeaturedPath())}
element={<WelcomePage />}
/>
)}
<Route
path={_FEATURED_PATH}
element={
<React.Suspense fallback={null}>
<FeaturedRooms />
</React.Suspense>
}
/>
<Route
path={_SERVER_PATH}
element={
<React.Suspense fallback={null}>
<PublicRooms />
</React.Suspense>
}
/>
</Route>
<Route path={CREATE_PATH} element={<Create />} />
<Route
path={INBOX_PATH}
element={
<PageRoot
nav={
<MobileFriendlyPageNav path={INBOX_PATH}>
<React.Suspense fallback={null}>
<Inbox />
</React.Suspense>
</MobileFriendlyPageNav>
}
>
<Outlet />
</PageRoot>
}
>
{mobile ? null : (
<Route
index
loader={() => redirect(getInboxNotificationsPath())}
element={<WelcomePage />}
/>
)}
<Route
path={_NOTIFICATIONS_PATH}
element={
<React.Suspense fallback={null}>
<Notifications />
</React.Suspense>
}
/>
<Route
path={_INVITES_PATH}
element={
<React.Suspense fallback={null}>
<Invites />
</React.Suspense>
}
/>
</Route>
</Route>
<Route path="/*" element={<p>Page not found</p>} />
</Route>,
);
if (hashRouter?.enabled) {
return createHashRouter(routes, { basename: hashRouter.basename });
}
return createBrowserRouter(routes, {
basename: import.meta.env.BASE_URL,
});
};