refactor(ui): update App routing structure and main entry point

Reorganize lazy-loaded route components and update import formatting.
Update main.tsx entry point to align with new theme system.
This commit is contained in:
ZhenYi 2026-05-18 20:43:49 +08:00
parent f77955074e
commit e3a79166c2
2 changed files with 216 additions and 82 deletions

View File

@ -1,76 +1,166 @@
import { lazy, Suspense } from "react";
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import { RootLayout } from "@/app/layout";
import { MeLayout } from "@/app/me";
import { ChannelLayout } from "@/app/channel";
import {
ProjectLayout,
ProjectSettingsLayout,
} from "@/app/project";
import { RedirectIfAuth, RequireAuth } from "@/components/auth";
import {
SettingsLayout,
} from "@/app/settings";
import RepoSettingsLayout from "@/app/project/repo/settings/RepoSettingsLayout";
import { ErrorBoundary } from "@/components/ui/ErrorBoundary";
import { lazy, Suspense } from "react"
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom"
import { RootLayout } from "@/app/layout"
import { MeLayout } from "@/app/me"
import { ChannelLayout } from "@/app/channel"
import { ProjectLayout, ProjectSettingsLayout } from "@/app/project"
import { RedirectIfAuth, RequireAuth } from "@/components/auth"
import { SettingsLayout } from "@/app/settings"
import RepoSettingsLayout from "@/app/project/repo/settings/RepoSettingsLayout"
import { ErrorBoundary } from "@/components/ui/ErrorBoundary"
// Lazy-loaded page components
const LoginPage = lazy(() => import("@/app/auth/login").then(m => ({ default: m.LoginPage })));
const RegisterPage = lazy(() => import("@/app/auth/register").then(m => ({ default: m.RegisterPage })));
const ForgotPasswordPage = lazy(() => import("@/app/auth/forgot-password").then(m => ({ default: m.ForgotPasswordPage })));
const ResetPasswordPage = lazy(() => import("@/app/auth/reset-password").then(m => ({ default: m.ResetPasswordPage })));
const TwoFactorPage = lazy(() => import("@/app/auth/two-factor").then(m => ({ default: m.TwoFactorPage })));
const VerifyEmailPage = lazy(() => import("@/app/auth/verify-email").then(m => ({ default: m.VerifyEmailPage })));
const ChangePasswordPage = lazy(() => import("@/app/auth/change-password").then(m => ({ default: m.ChangePasswordPage })));
const MePage = lazy(() => import("@/app/me").then(m => ({ default: m.MePage })));
const MyInvitationsPage = lazy(() => import("@/app/me/MyInvitationsPage"));
const ChatPage = lazy(() => import("@/app/chat").then(m => ({ default: m.ChatPage })));
const ExplorePage = lazy(() => import("@/app/explore/ExplorePage").then(m => ({ default: m.ExplorePage })));
const MyAccountPage = lazy(() => import("@/app/settings").then(m => ({ default: m.MyAccountPage })));
const BillingPage = lazy(() => import("@/app/settings").then(m => ({ default: m.BillingPage })));
const AppearancePage = lazy(() => import("@/app/settings").then(m => ({ default: m.AppearancePage })));
const NotificationsPage = lazy(() => import("@/app/settings").then(m => ({ default: m.NotificationsPage })));
const PasswordPage = lazy(() => import("@/app/settings").then(m => ({ default: m.PasswordPage })));
const EmailPage = lazy(() => import("@/app/settings").then(m => ({ default: m.EmailPage })));
const SshKeysPage = lazy(() => import("@/app/settings").then(m => ({ default: m.SshKeysPage })));
const AccessKeysPage = lazy(() => import("@/app/settings").then(m => ({ default: m.AccessKeysPage })));
const PushSettingsPage = lazy(() => import("@/app/settings").then(m => ({ default: m.PushSettingsPage })));
const ReposPage = lazy(() => import("@/app/project").then(m => ({ default: m.ReposPage })));
const IssuesPage = lazy(() => import("@/app/project").then(m => ({ default: m.IssuesPage })));
const NewIssuePage = lazy(() => import("@/app/project").then(m => ({ default: m.NewIssuePage })));
const SkillsPage = lazy(() => import("@/app/project").then(m => ({ default: m.SkillsPage })));
const BoardPage = lazy(() => import("@/app/project").then(m => ({ default: m.BoardPage })));
const ChannelPage = lazy(() => import("@/app/project").then(m => ({ default: m.ChannelPage })));
const RepoDetailPage = lazy(() => import("@/app/project").then(m => ({ default: m.RepoDetailPage })));
const CommitDetailPage = lazy(() => import("@/app/project").then(m => ({ default: m.CommitDetailPage })));
const IssueDetailPage = lazy(() => import("@/app/project").then(m => ({ default: m.IssueDetailPage })));
const SkillDetailPage = lazy(() => import("@/app/project").then(m => ({ default: m.SkillDetailPage })));
const PullRequestDetailPage = lazy(() => import("@/app/project").then(m => ({ default: m.PullRequestDetailPage })));
const ProjectJoinPage = lazy(() => import("@/app/project").then(m => ({ default: m.ProjectJoinPage })));
const ProjectInvitationPage = lazy(() => import("@/app/project").then(m => ({ default: m.ProjectInvitationPage })));
const GeneralSettings = lazy(() => import("@/app/project").then(m => ({ default: m.GeneralSettings })));
const MembersSettings = lazy(() => import("@/app/project").then(m => ({ default: m.MembersSettings })));
const AccessSettings = lazy(() => import("@/app/project").then(m => ({ default: m.AccessSettings })));
const LabelsSettings = lazy(() => import("@/app/project").then(m => ({ default: m.LabelsSettings })));
const BillingSettings = lazy(() => import("@/app/project").then(m => ({ default: m.BillingSettings })));
const CodePage = lazy(() => import("@/app/project/repo/code"));
const CommitsPage = lazy(() => import("@/app/project/repo/commits"));
const PullsPage = lazy(() => import("@/app/project/repo/pulls"));
const BranchesPage = lazy(() => import("@/app/project/repo/branches"));
const TagsPage = lazy(() => import("@/app/project/repo/tags"));
const RepoGeneralSettings = lazy(() => import("@/app/project/repo/settings/GeneralSettings"));
const BranchProtectionSettings = lazy(() => import("@/app/project/repo/settings/BranchProtectionSettings"));
const TreePage = lazy(() => import("@/app/project/repo/tree"));
const LoginPage = lazy(() =>
import("@/app/auth/login").then((m) => ({ default: m.LoginPage }))
)
const RegisterPage = lazy(() =>
import("@/app/auth/register").then((m) => ({ default: m.RegisterPage }))
)
const ForgotPasswordPage = lazy(() =>
import("@/app/auth/forgot-password").then((m) => ({
default: m.ForgotPasswordPage,
}))
)
const ResetPasswordPage = lazy(() =>
import("@/app/auth/reset-password").then((m) => ({
default: m.ResetPasswordPage,
}))
)
const TwoFactorPage = lazy(() =>
import("@/app/auth/two-factor").then((m) => ({ default: m.TwoFactorPage }))
)
const VerifyEmailPage = lazy(() =>
import("@/app/auth/verify-email").then((m) => ({
default: m.VerifyEmailPage,
}))
)
const ChangePasswordPage = lazy(() =>
import("@/app/auth/change-password").then((m) => ({
default: m.ChangePasswordPage,
}))
)
const MePage = lazy(() =>
import("@/app/me").then((m) => ({ default: m.MePage }))
)
const MyInvitationsPage = lazy(() => import("@/app/me/MyInvitationsPage"))
const ChatPage = lazy(() =>
import("@/app/chat").then((m) => ({ default: m.ChatPage }))
)
const ExplorePage = lazy(() =>
import("@/app/explore/ExplorePage").then((m) => ({ default: m.ExplorePage }))
)
const MyAccountPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.MyAccountPage }))
)
const BillingPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.BillingPage }))
)
const AppearancePage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.AppearancePage }))
)
const NotificationsPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.NotificationsPage }))
)
const PasswordPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.PasswordPage }))
)
const EmailPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.EmailPage }))
)
const SshKeysPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.SshKeysPage }))
)
const AccessKeysPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.AccessKeysPage }))
)
const PushSettingsPage = lazy(() =>
import("@/app/settings").then((m) => ({ default: m.PushSettingsPage }))
)
const ReposPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.ReposPage }))
)
const IssuesPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.IssuesPage }))
)
const NewIssuePage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.NewIssuePage }))
)
const SkillsPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.SkillsPage }))
)
const BoardPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.BoardPage }))
)
const ChannelPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.ChannelPage }))
)
const RepoDetailPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.RepoDetailPage }))
)
const CommitDetailPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.CommitDetailPage }))
)
const IssueDetailPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.IssueDetailPage }))
)
const SkillDetailPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.SkillDetailPage }))
)
const PullRequestDetailPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.PullRequestDetailPage }))
)
const ProjectJoinPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.ProjectJoinPage }))
)
const ProjectInvitationPage = lazy(() =>
import("@/app/project").then((m) => ({ default: m.ProjectInvitationPage }))
)
const GeneralSettings = lazy(() =>
import("@/app/project").then((m) => ({ default: m.GeneralSettings }))
)
const MembersSettings = lazy(() =>
import("@/app/project").then((m) => ({ default: m.MembersSettings }))
)
const AccessSettings = lazy(() =>
import("@/app/project").then((m) => ({ default: m.AccessSettings }))
)
const LabelsSettings = lazy(() =>
import("@/app/project").then((m) => ({ default: m.LabelsSettings }))
)
const BillingSettings = lazy(() =>
import("@/app/project").then((m) => ({ default: m.BillingSettings }))
)
const CodePage = lazy(() => import("@/app/project/repo/code"))
const CommitsPage = lazy(() => import("@/app/project/repo/commits"))
const PullsPage = lazy(() => import("@/app/project/repo/pulls"))
const BranchesPage = lazy(() => import("@/app/project/repo/branches"))
const TagsPage = lazy(() => import("@/app/project/repo/tags"))
const RepoGeneralSettings = lazy(
() => import("@/app/project/repo/settings/GeneralSettings")
)
const BranchProtectionSettings = lazy(
() => import("@/app/project/repo/settings/BranchProtectionSettings")
)
const TreePage = lazy(() => import("@/app/project/repo/tree"))
function PageLoader() {
return (
<div className="flex h-full items-center justify-center" style={{ backgroundColor: "var(--surface-ground)" }}>
<div className="flex flex-col items-center gap-3">
<div className="h-5 w-5 animate-spin rounded-full border-2" style={{ borderColor: "var(--border-strong)", borderTopColor: "var(--accent)" }} />
<span className="text-xs" style={{ color: "var(--text-muted)" }}>Loading...</span>
<div
className="flex h-full items-center justify-center"
style={{ backgroundColor: "var(--surface-ground)" }}
>
<div className="flex flex-col items-center gap-3 rounded-2xl border border-border/60 bg-card/80 px-8 py-6 shadow-sm backdrop-blur">
<div
className="h-5 w-5 animate-spin rounded-full border-2"
style={{
borderColor: "var(--border-strong)",
borderTopColor: "var(--accent)",
}}
/>
<span className="text-xs text-muted-foreground">Loading</span>
</div>
</div>
);
)
}
export default function App() {
@ -82,13 +172,22 @@ export default function App() {
<Route element={<RedirectIfAuth />}>
<Route path="/auth/login" element={<LoginPage />} />
<Route path="/auth/register" element={<RegisterPage />} />
<Route path="/auth/forgot-password" element={<ForgotPasswordPage />} />
<Route path="/auth/reset-password" element={<ResetPasswordPage />} />
<Route
path="/auth/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route
path="/auth/reset-password"
element={<ResetPasswordPage />}
/>
<Route path="/auth/two-factor" element={<TwoFactorPage />} />
<Route path="/auth/verify-email" element={<VerifyEmailPage />} />
</Route>
<Route path="/auth/change-password" element={<ChangePasswordPage />} />
<Route
path="/auth/change-password"
element={<ChangePasswordPage />}
/>
<Route element={<RequireAuth />}>
<Route element={<RootLayout />}>
@ -101,9 +200,18 @@ export default function App() {
<Route path="/me/followers" element={<MePage />} />
<Route path="/me/following" element={<MePage />} />
<Route path="/me/notify" element={<MePage />} />
<Route path="/me/invitations" element={<MyInvitationsPage />} />
<Route path="/me/chat" element={<ChatPage scope="personal" />} />
<Route path="/me/chat/:conversationId" element={<ChatPage scope="personal" />} />
<Route
path="/me/invitations"
element={<MyInvitationsPage />}
/>
<Route
path="/me/chat"
element={<ChatPage scope="personal" />}
/>
<Route
path="/me/chat/:conversationId"
element={<ChatPage scope="personal" />}
/>
<Route path="/explore" element={<ExplorePage />} />
</Route>
@ -123,8 +231,14 @@ export default function App() {
{/* Channel-based routes if any */}
</Route>
<Route path="/projects/:projectName/invitations" element={<ProjectInvitationPage />} />
<Route path="/:projectName/join" element={<ProjectJoinPage />} />
<Route
path="/projects/:projectName/invitations"
element={<ProjectInvitationPage />}
/>
<Route
path="/:projectName/join"
element={<ProjectJoinPage />}
/>
<Route path="/:projectName" element={<ProjectLayout />}>
<Route index element={<Navigate to="repos" replace />} />
@ -142,25 +256,43 @@ export default function App() {
<Route path="billing" element={<BillingSettings />} />
</Route>
<Route path="chat" element={<ChatPage scope="project" />} />
<Route path="chat/:conversationId" element={<ChatPage scope="project" />} />
<Route
path="chat/:conversationId"
element={<ChatPage scope="project" />}
/>
<Route path="channel/:roomId" element={<ChannelPage />} />
<Route path="issues/:issueNumber" element={<IssueDetailPage />} />
<Route path="skills/:skillSlug" element={<SkillDetailPage />} />
<Route
path="issues/:issueNumber"
element={<IssueDetailPage />}
/>
<Route
path="skills/:skillSlug"
element={<SkillDetailPage />}
/>
<Route path="repo/:repoName" element={<RepoDetailPage />}>
<Route element={<CodePage />}>
<Route index element={<TreePage />} />
<Route path="tree/:treeOid" element={<TreePage />} />
</Route>
<Route path="commits" element={<CommitsPage />} />
<Route path="commit/:commitOid" element={<CommitDetailPage />} />
<Route
path="commit/:commitOid"
element={<CommitDetailPage />}
/>
<Route path="pulls" element={<PullsPage />} />
<Route path="pulls/:prNumber" element={<PullRequestDetailPage />} />
<Route
path="pulls/:prNumber"
element={<PullRequestDetailPage />}
/>
<Route path="branches" element={<BranchesPage />} />
<Route path="tags" element={<TagsPage />} />
<Route path="settings" element={<RepoSettingsLayout />}>
<Route index element={<RepoGeneralSettings />} />
<Route path="general" element={<RepoGeneralSettings />} />
<Route path="branches" element={<BranchProtectionSettings />} />
<Route
path="branches"
element={<BranchProtectionSettings />}
/>
</Route>
</Route>
</Route>
@ -173,5 +305,5 @@ export default function App() {
</Suspense>
</ErrorBoundary>
</BrowserRouter>
);
)
}

View File

@ -7,6 +7,7 @@ import {ThemeProvider} from "@/components/theme-provider.tsx"
import {Toaster} from "@/components/ui/sonner"
import {performMaintenance} from "@/lib/db/maintenance";
import {applyThemePreset} from "@/components/theme/ThemePresetSelector";
import {loadThemeVars} from "@/lib/theme-vars";
import App from "@/App.tsx";
import {initRum} from "@/rum-core";
import {RumUserContext} from "@/rum";
@ -16,6 +17,7 @@ initRum();
const PRESET_KEY = "app-theme-preset";
const savedPreset = localStorage.getItem(PRESET_KEY) || "soft-mono";
applyThemePreset(savedPreset);
loadThemeVars();
performMaintenance().catch(console.error);
@ -38,4 +40,4 @@ createRoot(document.getElementById("root")!).render(
</ThemeProvider>
</QueryClientProvider>
</StrictMode>
)
)