From 4209e6df43e1667c00bef759a118ea9929849da5 Mon Sep 17 00:00:00 2001 From: christiangruender <131187233+christiangruender@users.noreply.github.com> Date: Mon, 10 Nov 2025 17:52:36 +0100 Subject: [PATCH 1/2] Improve sidebar navigation --- .../common/overall-layout/layout.tsx | 112 +++++++++++++++-- .../overall-layout/menus/multisig-wallet.tsx | 119 +++++------------- .../common/overall-layout/menus/wallets.tsx | 73 +++-------- .../common/overall-layout/wallet-selector.tsx | 114 +++++++++++++++++ src/components/pages/homepage/index.tsx | 6 + src/components/ui/mobile-navigation.tsx | 65 ++++++++-- 6 files changed, 327 insertions(+), 162 deletions(-) create mode 100644 src/components/common/overall-layout/wallet-selector.tsx diff --git a/src/components/common/overall-layout/layout.tsx b/src/components/common/overall-layout/layout.tsx index 914bd2f1..29b7050b 100644 --- a/src/components/common/overall-layout/layout.tsx +++ b/src/components/common/overall-layout/layout.tsx @@ -8,12 +8,14 @@ import { api } from "@/utils/api"; import useUser from "@/hooks/useUser"; import { useUserStore } from "@/lib/zustand/user"; import useAppWallet from "@/hooks/useAppWallet"; +import useMultisigWallet from "@/hooks/useMultisigWallet"; import SessionProvider from "@/components/SessionProvider"; import { getServerSession } from "next-auth"; -// import MenuWallets from "@/components/common/overall-layout/menus/wallets"; +import MenuWallets from "@/components/common/overall-layout/menus/wallets"; import MenuWallet from "@/components/common/overall-layout/menus/multisig-wallet"; +import WalletSelector from "@/components/common/overall-layout/wallet-selector"; import { WalletDataLoaderWrapper, DialogReportWrapper, @@ -69,6 +71,7 @@ export default function RootLayout({ const { user, isLoading } = useUser(); const router = useRouter(); const { appWallet } = useAppWallet(); + const { multisigWallet } = useMultisigWallet(); const { generateNsec } = useNostrChat(); const userAddress = useUserStore((state) => state.userAddress); @@ -164,6 +167,43 @@ export default function RootLayout({ const walletPageNames = walletPageRoute ? walletPageRoute.split("/") : []; const pageIsPublic = publicRoutes.includes(router.pathname); const isLoggedIn = !!user; + const isHomepage = router.pathname === "/"; + + // Keep track of the last visited wallet to show wallet menu even on other pages + const [lastVisitedWalletId, setLastVisitedWalletId] = React.useState(null); + const [lastVisitedWalletName, setLastVisitedWalletName] = React.useState(null); + const [lastWalletStakingEnabled, setLastWalletStakingEnabled] = React.useState(null); + + React.useEffect(() => { + const walletId = router.query.wallet as string | undefined; + if (walletId && isWalletPath && appWallet && multisigWallet) { + setLastVisitedWalletId(walletId); + setLastVisitedWalletName(appWallet.name); + // Check if staking is enabled for this wallet + try { + const stakingEnabled = multisigWallet.stakingEnabled(); + setLastWalletStakingEnabled(stakingEnabled); + } catch (error) { + // Don't update state on error - keep the last known value + console.error("Error checking staking status:", error); + } + } + }, [router.query.wallet, isWalletPath, appWallet, multisigWallet]); + + const clearWalletContext = React.useCallback(() => { + setLastVisitedWalletId(null); + setLastVisitedWalletName(null); + setLastWalletStakingEnabled(null); + }, []); + + // Clear wallet context when navigating to homepage + React.useEffect(() => { + if (isHomepage && lastVisitedWalletId) { + clearWalletContext(); + } + }, [isHomepage, lastVisitedWalletId, clearWalletContext]); + + const showWalletMenu = isLoggedIn && (isWalletPath || lastVisitedWalletId); return (
@@ -175,11 +215,21 @@ export default function RootLayout({ data-header="main" >
- {/* Mobile menu button - only in wallet context */} - {isWalletPath && } + {/* Mobile menu button - hidden only on public homepage (not logged in) */} + {(isLoggedIn || !isHomepage) && ( + + )} {/* Logo - in fixed-width container matching sidebar width */} -
+
{/* Content area with sidebar + main */} -
- {/* Sidebar for larger screens - only in wallet context */} - {isWalletPath && ( +
+ {/* Sidebar for larger screens - hidden only on public homepage (not logged in) */} + {(isLoggedIn || !isHomepage) && (
+
); } diff --git a/src/components/common/overall-layout/wallet-selector.tsx b/src/components/common/overall-layout/wallet-selector.tsx new file mode 100644 index 00000000..2d110f48 --- /dev/null +++ b/src/components/common/overall-layout/wallet-selector.tsx @@ -0,0 +1,114 @@ +import { useState, useEffect } from "react"; +import { useRouter } from "next/router"; +import { ChevronDown, ChevronUp, Wallet2, Plus, House } from "lucide-react"; +import useUserWallets from "@/hooks/useUserWallets"; +import useAppWallet from "@/hooks/useAppWallet"; +import WalletNavLink from "@/components/common/overall-layout/wallet-nav-link"; +import MenuLink from "@/components/common/overall-layout/menus/menu-link"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; + +interface WalletSelectorProps { + fallbackWalletName?: string | null; + onClearWallet?: () => void; +} + +export default function WalletSelector({ fallbackWalletName, onClearWallet }: WalletSelectorProps = {}) { + const router = useRouter(); + const { wallets } = useUserWallets(); + const { appWallet } = useAppWallet(); + const [open, setOpen] = useState(false); + + const displayName = appWallet?.name || fallbackWalletName || "Select Wallet"; + + const handleHomeClick = () => { + if (onClearWallet) { + onClearWallet(); + } + void router.push("/"); + }; + + // Close dropdown on route change + useEffect(() => { + const handleRouteChange = () => { + setOpen(false); + }; + router.events.on("routeChangeStart", handleRouteChange); + return () => { + router.events.off("routeChangeStart", handleRouteChange); + }; + }, [router.events]); + + if (!wallets) return null; + + return ( +
+
+ {/* Wallet Selector */} +
+ + + + + + {wallets + .filter((wallet) => !wallet.isArchived) + .sort((a, b) => a.name.localeCompare(b.name)) + .map((wallet) => ( + + + + ))} + + + + + + +
+ + {/* Home Link */} +
+ +
+
+
+ ); +} diff --git a/src/components/pages/homepage/index.tsx b/src/components/pages/homepage/index.tsx index e9ebfda6..307178f2 100644 --- a/src/components/pages/homepage/index.tsx +++ b/src/components/pages/homepage/index.tsx @@ -462,6 +462,12 @@ export function PageHomepage() {

+ + Resources + void; + stakingEnabled?: boolean; + isWalletPath?: boolean; } -export function MobileNavigation({ isWalletPath }: MobileNavigationProps) { +export function MobileNavigation({ showWalletMenu, isLoggedIn, walletId, fallbackWalletName, onClearWallet, stakingEnabled, isWalletPath }: MobileNavigationProps) { + const router = useRouter(); const [open, setOpen] = useState(false); - const { user } = useUser(); return ( <> @@ -116,11 +125,51 @@ export function MobileNavigation({ isWalletPath }: MobileNavigationProps) { From b56e80b84c9700573bb97c7ee8636455f27cc836 Mon Sep 17 00:00:00 2001 From: christiangruender <131187233+christiangruender@users.noreply.github.com> Date: Mon, 10 Nov 2025 18:27:33 +0100 Subject: [PATCH 2/2] fix(layout): ensure showWalletMenu returns boolean type --- src/components/common/overall-layout/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/overall-layout/layout.tsx b/src/components/common/overall-layout/layout.tsx index 29b7050b..6974f13c 100644 --- a/src/components/common/overall-layout/layout.tsx +++ b/src/components/common/overall-layout/layout.tsx @@ -203,7 +203,7 @@ export default function RootLayout({ } }, [isHomepage, lastVisitedWalletId, clearWalletContext]); - const showWalletMenu = isLoggedIn && (isWalletPath || lastVisitedWalletId); + const showWalletMenu = isLoggedIn && (isWalletPath || !!lastVisitedWalletId); return (