Skip to content

Commit 8102212

Browse files
committed
chore: simplify page loading logic
1 parent c5d9770 commit 8102212

File tree

8 files changed

+47
-122
lines changed

8 files changed

+47
-122
lines changed

web/src/components/Skeleton.tsx

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,49 @@
11
import { cn } from "@/lib/utils";
22

3-
interface Props {
3+
interface SkeletonProps {
44
showCreator?: boolean;
55
count?: number;
66
}
77

8-
// Memo card skeleton component for list loading states
9-
const MemoCardSkeleton = ({ showCreator = false, index = 0 }: { showCreator?: boolean; index?: number }) => (
10-
<div className="relative flex flex-col justify-start items-start bg-card w-full px-4 py-3 mb-2 gap-2 rounded-lg border border-border animate-pulse">
11-
{/* Header section */}
12-
<div className="w-full flex flex-row justify-between items-center gap-2">
13-
<div className="w-auto max-w-[calc(100%-8rem)] grow flex flex-row justify-start items-center">
8+
const skeletonBase = "bg-muted/70 rounded animate-pulse";
9+
10+
const MemoCardSkeleton = ({ showCreator, index }: { showCreator?: boolean; index: number }) => (
11+
<div className="relative flex flex-col bg-card w-full px-4 py-3 mb-2 gap-2 rounded-lg border border-border">
12+
<div className="w-full flex justify-between items-center gap-2">
13+
<div className="grow flex items-center max-w-[calc(100%-8rem)]">
1414
{showCreator ? (
15-
<div className="w-full flex flex-row justify-start items-center gap-2">
16-
<div className="w-8 h-8 rounded-full bg-muted shrink-0" />
17-
<div className="w-full flex flex-col justify-center items-start gap-1">
18-
<div className="h-4 w-24 bg-muted rounded" />
19-
<div className="h-3 w-16 bg-muted rounded" />
15+
<div className="w-full flex items-center gap-2">
16+
<div className={cn("w-8 h-8 rounded-full shrink-0", skeletonBase)} />
17+
<div className="flex flex-col gap-1">
18+
<div className={cn("h-4 w-24", skeletonBase)} />
19+
<div className={cn("h-3 w-16", skeletonBase)} />
2020
</div>
2121
</div>
2222
) : (
23-
<div className="h-4 w-32 bg-muted rounded" />
23+
<div className={cn("h-4 w-32", skeletonBase)} />
2424
)}
2525
</div>
26-
{/* Action buttons skeleton */}
27-
<div className="flex flex-row gap-2">
28-
<div className="w-4 h-4 bg-muted rounded" />
29-
<div className="w-4 h-4 bg-muted rounded" />
26+
<div className="flex gap-2">
27+
<div className={cn("w-4 h-4", skeletonBase)} />
28+
<div className={cn("w-4 h-4", skeletonBase)} />
3029
</div>
3130
</div>
32-
33-
{/* Content section */}
34-
<div className="w-full flex flex-col gap-2">
35-
<div className="space-y-2">
36-
<div className={cn("h-4 bg-muted rounded", index % 3 === 0 ? "w-full" : index % 3 === 1 ? "w-4/5" : "w-5/6")} />
37-
<div className={cn("h-4 bg-muted rounded", index % 2 === 0 ? "w-3/4" : "w-4/5")} />
38-
{index % 2 === 0 && <div className="h-4 w-2/3 bg-muted rounded" />}
39-
</div>
31+
<div className="space-y-2">
32+
<div className={cn("h-4", skeletonBase, index % 3 === 0 ? "w-full" : index % 3 === 1 ? "w-4/5" : "w-5/6")} />
33+
<div className={cn("h-4", skeletonBase, index % 2 === 0 ? "w-3/4" : "w-4/5")} />
34+
{index % 2 === 0 && <div className={cn("h-4 w-2/3", skeletonBase)} />}
4035
</div>
4136
</div>
4237
);
4338

4439
/**
45-
* Skeleton loading state for memo lists.
46-
* Use this for initial memo list loading and pagination.
47-
* For generic page/route loading, use Spinner instead.
40+
* Memo list loading skeleton - shows card structure while loading.
41+
* Only use for memo lists in PagedMemoList component.
4842
*/
49-
const Skeleton = ({ showCreator = false, count = 4 }: Props) => (
43+
const Skeleton = ({ showCreator = false, count = 4 }: SkeletonProps) => (
5044
<div className="w-full max-w-2xl mx-auto">
51-
{Array.from({ length: count }).map((_, index) => (
52-
<MemoCardSkeleton key={index} showCreator={showCreator} index={index} />
45+
{Array.from({ length: count }, (_, i) => (
46+
<MemoCardSkeleton key={i} showCreator={showCreator} index={i} />
5347
))}
5448
</div>
5549
);

web/src/components/Spinner.tsx

Lines changed: 0 additions & 19 deletions
This file was deleted.

web/src/components/UserMemoMap/UserMemoMap.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { MapContainer, Marker, Popup, useMap } from "react-leaflet";
88
import MarkerClusterGroup from "react-leaflet-cluster";
99
import { Link } from "react-router-dom";
1010
import { defaultMarkerIcon, ThemedTileLayer } from "@/components/map/map-utils";
11-
import Spinner from "@/components/Spinner";
1211
import { useInfiniteMemos } from "@/hooks/useMemoQueries";
1312
import { cn } from "@/lib/utils";
1413
import { State } from "@/types/proto/api/v1/common_pb";
@@ -64,13 +63,7 @@ const UserMemoMap = ({ creator, className }: Props) => {
6463

6564
const memosWithLocation = useMemo(() => data?.pages.flatMap((page) => page.memos).filter((memo) => memo.location) || [], [data]);
6665

67-
if (isLoading) {
68-
return (
69-
<div className="w-full h-[380px] flex items-center justify-center rounded-xl border border-border bg-muted/30">
70-
<Spinner className="w-8 h-8" />
71-
</div>
72-
);
73-
}
66+
if (isLoading) return null;
7467

7568
const defaultCenter = { lat: 48.8566, lng: 2.3522 };
7669

web/src/layouts/RootLayout.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { Suspense, useEffect, useMemo } from "react";
1+
import { useEffect, useMemo } from "react";
22
import { Outlet, useLocation, useSearchParams } from "react-router-dom";
33
import usePrevious from "react-use/lib/usePrevious";
44
import Navigation from "@/components/Navigation";
5-
import Spinner from "@/components/Spinner";
65
import { useInstance } from "@/contexts/InstanceContext";
76
import { useMemoFilterContext } from "@/contexts/MemoFilterContext";
87
import useCurrentUser from "@/hooks/useCurrentUser";
@@ -47,15 +46,7 @@ const RootLayout = () => {
4746
</div>
4847
)}
4948
<main className="w-full h-auto grow shrink flex flex-col justify-start items-center">
50-
<Suspense
51-
fallback={
52-
<div className="w-full h-64 flex items-center justify-center">
53-
<Spinner size="lg" />
54-
</div>
55-
}
56-
>
57-
<Outlet />
58-
</Suspense>
49+
<Outlet />
5950
</main>
6051
</div>
6152
);

web/src/main.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { RouterProvider } from "react-router-dom";
88
import "./i18n";
99
import "./index.css";
1010
import { ErrorBoundary } from "@/components/ErrorBoundary";
11-
import Spinner from "@/components/Spinner";
1211
import { AuthProvider, useAuth } from "@/contexts/AuthContext";
1312
import { InstanceProvider, useInstance } from "@/contexts/InstanceContext";
1413
import { ViewProvider } from "@/contexts/ViewContext";
@@ -41,11 +40,7 @@ function AppInitializer({ children }: { children: React.ReactNode }) {
4140
}, [initAuth, initInstance]);
4241

4342
if (!authInitialized || !instanceInitialized) {
44-
return (
45-
<div className="w-full h-screen flex items-center justify-center">
46-
<Spinner size="lg" />
47-
</div>
48-
);
43+
return null;
4944
}
5045

5146
return <>{children}</>;

web/src/pages/AuthCallback.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { timestampDate } from "@bufbuild/protobuf/wkt";
22
import { useEffect, useState } from "react";
33
import { useSearchParams } from "react-router-dom";
44
import { setAccessToken } from "@/auth-state";
5-
import Spinner from "@/components/Spinner";
65
import { authServiceClient } from "@/connect";
76
import { useAuth } from "@/contexts/AuthContext";
87
import { absolutifyLink } from "@/helpers/utils";
@@ -110,13 +109,11 @@ const AuthCallback = () => {
110109
})();
111110
}, [searchParams, navigateTo]);
112111

112+
if (state.loading) return null;
113+
113114
return (
114115
<div className="p-4 py-24 w-full h-full flex justify-center items-center">
115-
{state.loading ? (
116-
<Spinner size="lg" />
117-
) : (
118-
<div className="max-w-lg font-mono whitespace-pre-wrap opacity-80">{state.errorMessage}</div>
119-
)}
116+
<div className="max-w-lg font-mono whitespace-pre-wrap opacity-80">{state.errorMessage}</div>
120117
</div>
121118
);
122119
};

web/src/router/MemoDetailRedirect.tsx

Lines changed: 0 additions & 8 deletions
This file was deleted.

web/src/router/index.tsx

Lines changed: 15 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import type { ComponentType } from "react";
2-
import { lazy, Suspense } from "react";
1+
import { lazy } from "react";
32
import { createBrowserRouter } from "react-router-dom";
43
import App from "@/App";
5-
import Spinner from "@/components/Spinner";
64
import MainLayout from "@/layouts/MainLayout";
75
import RootLayout from "@/layouts/RootLayout";
86
import Home from "@/pages/Home";
@@ -20,27 +18,13 @@ const Setting = lazy(() => import("@/pages/Setting"));
2018
const SignIn = lazy(() => import("@/pages/SignIn"));
2119
const SignUp = lazy(() => import("@/pages/SignUp"));
2220
const UserProfile = lazy(() => import("@/pages/UserProfile"));
23-
const MemoDetailRedirect = lazy(() => import("./MemoDetailRedirect"));
2421

2522
import { ROUTES } from "./routes";
2623

2724
// Backward compatibility alias
2825
export const Routes = ROUTES;
2926
export { ROUTES };
3027

31-
// Helper component to reduce Suspense boilerplate for lazy routes
32-
const LazyRoute = ({ component: Component }: { component: ComponentType }) => (
33-
<Suspense
34-
fallback={
35-
<div className="w-full h-64 flex items-center justify-center">
36-
<Spinner size="lg" />
37-
</div>
38-
}
39-
>
40-
<Component />
41-
</Suspense>
42-
);
43-
4428
const router = createBrowserRouter([
4529
{
4630
path: "/",
@@ -49,10 +33,10 @@ const router = createBrowserRouter([
4933
{
5034
path: Routes.AUTH,
5135
children: [
52-
{ path: "", element: <LazyRoute component={SignIn} /> },
53-
{ path: "admin", element: <LazyRoute component={AdminSignIn} /> },
54-
{ path: "signup", element: <LazyRoute component={SignUp} /> },
55-
{ path: "callback", element: <LazyRoute component={AuthCallback} /> },
36+
{ path: "", element: <SignIn /> },
37+
{ path: "admin", element: <AdminSignIn /> },
38+
{ path: "signup", element: <SignUp /> },
39+
{ path: "callback", element: <AuthCallback /> },
5640
],
5741
},
5842
{
@@ -63,20 +47,18 @@ const router = createBrowserRouter([
6347
element: <MainLayout />,
6448
children: [
6549
{ path: "", element: <Home /> },
66-
{ path: Routes.EXPLORE, element: <LazyRoute component={Explore} /> },
67-
{ path: Routes.ARCHIVED, element: <LazyRoute component={Archived} /> },
68-
{ path: "u/:username", element: <LazyRoute component={UserProfile} /> },
50+
{ path: Routes.EXPLORE, element: <Explore /> },
51+
{ path: Routes.ARCHIVED, element: <Archived /> },
52+
{ path: "u/:username", element: <UserProfile /> },
6953
],
7054
},
71-
{ path: Routes.ATTACHMENTS, element: <LazyRoute component={Attachments} /> },
72-
{ path: Routes.INBOX, element: <LazyRoute component={Inboxes} /> },
73-
{ path: Routes.SETTING, element: <LazyRoute component={Setting} /> },
74-
{ path: "memos/:uid", element: <LazyRoute component={MemoDetail} /> },
75-
// Redirect old path to new path
76-
{ path: "m/:uid", element: <LazyRoute component={MemoDetailRedirect} /> },
77-
{ path: "403", element: <LazyRoute component={PermissionDenied} /> },
78-
{ path: "404", element: <LazyRoute component={NotFound} /> },
79-
{ path: "*", element: <LazyRoute component={NotFound} /> },
55+
{ path: Routes.ATTACHMENTS, element: <Attachments /> },
56+
{ path: Routes.INBOX, element: <Inboxes /> },
57+
{ path: Routes.SETTING, element: <Setting /> },
58+
{ path: "memos/:uid", element: <MemoDetail /> },
59+
{ path: "403", element: <PermissionDenied /> },
60+
{ path: "404", element: <NotFound /> },
61+
{ path: "*", element: <NotFound /> },
8062
],
8163
},
8264
],

0 commit comments

Comments
 (0)