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

View File

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