From f95adeecf159ada04a37ee6a23a8ca86e1883def Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Fri, 30 Oct 2026 13:12:06 +0700 Subject: [PATCH] perf: faster shell, lazy wallet stack, serialized Amber and navigation polish --- src/AppRouter.tsx | 12 +- src/components/FundingGoalCard.tsx | 6 +- src/components/Layout.tsx | 37 ++++- src/components/LazyZapDialog.tsx | 72 ++++++++++ src/components/RoutePreloader.tsx | 82 +++++++++++ src/components/ZapButton.tsx | 6 +- src/components/ZapDialog.tsx | 47 ++++-- src/index.css | 7 + src/lib/capacitorAmberSigner.ts | 220 ++++++++++++++++++++--------- src/pages/HomePage.native.tsx | 7 + src/pages/HomePage.tsx | 11 ++ vite.config.ts | 15 +- 12 files changed, 427 insertions(+), 95 deletions(-) create mode 100644 src/components/LazyZapDialog.tsx create mode 100644 src/components/RoutePreloader.tsx create mode 100644 src/pages/HomePage.native.tsx create mode 100644 src/pages/HomePage.tsx diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index 9c35736..a7d36a4 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -6,10 +6,11 @@ import { BECOME_ROLES } from "./lib/becomeRoles"; import { DeepLinkHandler } from "./components/DeepLinkHandler"; import { RouteErrorBoundary } from "./components/RouteErrorBoundary"; import { Layout } from "./components/Layout"; +import { RoutePreloader } from "./components/RoutePreloader"; -// MapPage is eager: it is the homepage and a lazy import here used to leave a -// blank Suspense fallback on slow native WebViews before the map appeared. -import MapPage from "./pages/MapPage"; +// HomePage resolves to a lazy map on web (smaller first entry) and to the +// eager MapPage via a Capacitor-only Vite alias on Android. +import HomePage from "@/pages/HomePage"; // Lazy load everything else — each page becomes its own JS chunk const Index = lazyWithRetry(() => import("./pages/Index")); @@ -99,6 +100,7 @@ export function AppRouter() { return ( + {/* Per-route boundary: a crash in one page shows a recoverable message instead of blanking the whole app. Resets automatically on navigate @@ -111,9 +113,9 @@ export function AppRouter() { navigation. Pages no longer wrap themselves in . */} }> {/* Map is the homepage */} - } /> + } /> {/* /map redirects to / */} - } /> + } /> {/* Legacy home page still accessible */} } /> } /> diff --git a/src/components/FundingGoalCard.tsx b/src/components/FundingGoalCard.tsx index e62c73c..4b966bc 100644 --- a/src/components/FundingGoalCard.tsx +++ b/src/components/FundingGoalCard.tsx @@ -1,5 +1,5 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { ZapDialog } from '@/components/ZapDialog'; +import { LazyZapDialog } from '@/components/LazyZapDialog'; import { useZaps } from '@/hooks/useZaps'; import { useWallet } from '@/hooks/useWallet'; import { cn } from '@/lib/utils'; @@ -64,7 +64,7 @@ export function FundingGoalCard({ )}

- + - + ); diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index f30a2cd..c01eddb 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -111,6 +111,30 @@ function hasCashuWalletHint(): boolean { } } +/** + * Page-level Suspense fallback. Keeps the header and bottom nav mounted while a + * lazy route chunk loads, so tapping a menu item never blanks the whole app. + * The fade is delayed slightly: a fast chunk resolves before it becomes visible. + */ +function RouteLoadingFallback() { + return ( +