From be0e0bfa2972690c37ee6c170689a9910a38db7e Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 18 Jan 2026 08:42:48 +0000 Subject: [PATCH] refactor: move wallet functionality to user menu Move wallet connection and info from separate header button into the user menu dropdown for better organization. Changes: - Remove standalone WalletButton component - Add wallet section to user menu dropdown - Show "Connect Wallet" option when no wallet is connected - Display wallet balance and alias when connected - Clicking wallet info opens detailed dialog with: - Balance (without suffix) - Wallet name/alias - Lightning address (lud16) - Supported NWC methods - Connected relay URLs - Disconnect button This consolidates all user-related settings (account, relays, blossom servers, wallet) in one consistent location. --- src/components/WalletButton.tsx | 169 ---------------------------- src/components/layouts/AppShell.tsx | 6 +- src/components/nostr/user-menu.tsx | 161 +++++++++++++++++++++++++- 3 files changed, 160 insertions(+), 176 deletions(-) delete mode 100644 src/components/WalletButton.tsx diff --git a/src/components/WalletButton.tsx b/src/components/WalletButton.tsx deleted file mode 100644 index 69f9a98..0000000 --- a/src/components/WalletButton.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import { useState } from "react"; -import { Wallet, Zap, X } from "lucide-react"; -import { useGrimoire } from "@/core/state"; -import { Button } from "@/components/ui/button"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; -import ConnectWalletDialog from "@/components/ConnectWalletDialog"; -import { toast } from "sonner"; - -export default function WalletButton() { - const { state, disconnectNWC } = useGrimoire(); - const nwcConnection = state.nwcConnection; - const [showConnectWallet, setShowConnectWallet] = useState(false); - const [showWalletInfo, setShowWalletInfo] = useState(false); - - function formatBalance(millisats?: number): string { - if (millisats === undefined) return "—"; - const sats = Math.floor(millisats / 1000); - return sats.toLocaleString(); - } - - function handleDisconnect() { - disconnectNWC(); - setShowWalletInfo(false); - toast.success("Wallet disconnected"); - } - - function handleClick() { - if (nwcConnection) { - setShowWalletInfo(true); - } else { - setShowConnectWallet(true); - } - } - - return ( - <> - - - {/* Wallet Info Dialog */} - {nwcConnection && ( - - - - Wallet Info - - Connected Lightning wallet details - - - -
- {/* Balance */} -
- Balance: - - {formatBalance(nwcConnection.balance)} - -
- - {/* Wallet Alias */} - {nwcConnection.info?.alias && ( -
- Wallet: - - {nwcConnection.info.alias} - -
- )} - - {/* Lightning Address */} - {nwcConnection.lud16 && ( -
- - Address: - - - {nwcConnection.lud16} - -
- )} - - {/* Supported Methods */} - {nwcConnection.info?.methods && - nwcConnection.info.methods.length > 0 && ( -
- - Supported Methods: - -
- {nwcConnection.info.methods.map((method) => ( - - {method} - - ))} -
-
- )} - - {/* Relays */} -
- Relays: -
- {nwcConnection.relays.map((relay) => ( -
- {relay} -
- ))} -
-
- - {/* Disconnect Button */} - -
-
-
- )} - - {/* Wallet Button */} - {nwcConnection ? ( - - ) : ( - - )} - - ); -} diff --git a/src/components/layouts/AppShell.tsx b/src/components/layouts/AppShell.tsx index 9b10dd0..3f82958 100644 --- a/src/components/layouts/AppShell.tsx +++ b/src/components/layouts/AppShell.tsx @@ -10,7 +10,6 @@ import CommandLauncher from "../CommandLauncher"; import { GlobalAuthPrompt } from "../GlobalAuthPrompt"; import { SpellbookDropdown } from "../SpellbookDropdown"; import UserMenu from "../nostr/user-menu"; -import WalletButton from "../WalletButton"; import { AppShellContext } from "./AppShellContext"; interface AppShellProps { @@ -77,10 +76,7 @@ export function AppShell({ children, hideBottomBar = false }: AppShellProps) { -
- - -
+
{children} diff --git a/src/components/nostr/user-menu.tsx b/src/components/nostr/user-menu.tsx index 4bb555e..b746452 100644 --- a/src/components/nostr/user-menu.tsx +++ b/src/components/nostr/user-menu.tsx @@ -1,4 +1,4 @@ -import { User, HardDrive, Palette } from "lucide-react"; +import { User, HardDrive, Palette, Wallet, Zap, X } from "lucide-react"; import accounts from "@/services/accounts"; import { useProfile } from "@/hooks/useProfile"; import { use$ } from "applesauce-react/hooks"; @@ -17,13 +17,22 @@ import { DropdownMenuSubTrigger, DropdownMenuSubContent, } from "@/components/ui/dropdown-menu"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import Nip05 from "./nip05"; import { RelayLink } from "./RelayLink"; import SettingsDialog from "@/components/SettingsDialog"; import LoginDialog from "./LoginDialog"; +import ConnectWalletDialog from "@/components/ConnectWalletDialog"; import { useState } from "react"; import { useTheme } from "@/lib/themes"; +import { toast } from "sonner"; function UserAvatar({ pubkey }: { pubkey: string }) { const profile = useProfile(pubkey); @@ -56,11 +65,14 @@ function UserLabel({ pubkey }: { pubkey: string }) { export default function UserMenu() { const account = use$(accounts.active$); - const { state, addWindow } = useGrimoire(); + const { state, addWindow, disconnectNWC } = useGrimoire(); const relays = state.activeAccount?.relays; const blossomServers = state.activeAccount?.blossomServers; + const nwcConnection = state.nwcConnection; const [showSettings, setShowSettings] = useState(false); const [showLogin, setShowLogin] = useState(false); + const [showConnectWallet, setShowConnectWallet] = useState(false); + const [showWalletInfo, setShowWalletInfo] = useState(false); const { themeId, setTheme, availableThemes } = useTheme(); function openProfile() { @@ -77,10 +89,118 @@ export default function UserMenu() { accounts.removeAccount(account); } + function formatBalance(millisats?: number): string { + if (millisats === undefined) return "—"; + const sats = Math.floor(millisats / 1000); + return sats.toLocaleString(); + } + + function handleDisconnectWallet() { + disconnectNWC(); + setShowWalletInfo(false); + toast.success("Wallet disconnected"); + } + return ( <> + + + {/* Wallet Info Dialog */} + {nwcConnection && ( + + + + Wallet Info + + Connected Lightning wallet details + + + +
+ {/* Balance */} +
+ Balance: + + {formatBalance(nwcConnection.balance)} + +
+ + {/* Wallet Alias */} + {nwcConnection.info?.alias && ( +
+ Wallet: + + {nwcConnection.info.alias} + +
+ )} + + {/* Lightning Address */} + {nwcConnection.lud16 && ( +
+ + Address: + + + {nwcConnection.lud16} + +
+ )} + + {/* Supported Methods */} + {nwcConnection.info?.methods && + nwcConnection.info.methods.length > 0 && ( +
+ + Supported Methods: + +
+ {nwcConnection.info.methods.map((method) => ( + + {method} + + ))} +
+
+ )} + + {/* Relays */} +
+ Relays: +
+ {nwcConnection.relays.map((relay) => ( +
+ {relay} +
+ ))} +
+
+ + {/* Disconnect Button */} + +
+
+
+ )} +