mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-10 23:47:12 +02:00
feat: improve wallet UX with profile-based naming and better layout
Improvements to NWC wallet UI: - Add separator between user info and wallet section in menu - Show wallet icon instead of zap icon for better clarity - Display connection status indicator (green/red dot) in both menu and dialog - Make wallet service username clickable in wallet info dialog to open profile - Use wallet relays as hints when fetching service profile for better resolution - Enhanced useProfile hook to accept optional relay hints parameter The wallet now properly resolves service profiles using the NWC relay and shows visual connection status at a glance.
This commit is contained in:
@@ -1,12 +1,4 @@
|
||||
import {
|
||||
User,
|
||||
HardDrive,
|
||||
Palette,
|
||||
Wallet,
|
||||
Zap,
|
||||
X,
|
||||
RefreshCw,
|
||||
} from "lucide-react";
|
||||
import { User, HardDrive, Palette, Wallet, X, RefreshCw } from "lucide-react";
|
||||
import accounts from "@/services/accounts";
|
||||
import { useProfile } from "@/hooks/useProfile";
|
||||
import { use$ } from "applesauce-react/hooks";
|
||||
@@ -84,11 +76,19 @@ export default function UserMenu() {
|
||||
const [showWalletInfo, setShowWalletInfo] = useState(false);
|
||||
const { themeId, setTheme, availableThemes } = useTheme();
|
||||
|
||||
// Get wallet service profile for display name
|
||||
const walletServiceProfile = useProfile(nwcConnection?.service);
|
||||
// Get wallet service profile for display name, using wallet relays as hints
|
||||
const walletServiceProfile = useProfile(
|
||||
nwcConnection?.service,
|
||||
nwcConnection?.relays,
|
||||
);
|
||||
|
||||
// Use wallet hook for real-time balance and methods
|
||||
const { disconnect: disconnectWallet, refreshBalance, balance } = useWallet();
|
||||
const {
|
||||
disconnect: disconnectWallet,
|
||||
refreshBalance,
|
||||
balance,
|
||||
wallet,
|
||||
} = useWallet();
|
||||
|
||||
function openProfile() {
|
||||
if (!account?.pubkey) return;
|
||||
@@ -138,6 +138,16 @@ export default function UserMenu() {
|
||||
);
|
||||
}
|
||||
|
||||
function openWalletServiceProfile() {
|
||||
if (!nwcConnection?.service) return;
|
||||
addWindow(
|
||||
"profile",
|
||||
{ pubkey: nwcConnection.service },
|
||||
`Profile ${nwcConnection.service.slice(0, 8)}...`,
|
||||
);
|
||||
setShowWalletInfo(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsDialog open={showSettings} onOpenChange={setShowSettings} />
|
||||
@@ -185,7 +195,27 @@ export default function UserMenu() {
|
||||
{/* Wallet Name */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-muted-foreground">Wallet:</span>
|
||||
<span className="text-sm font-medium">{getWalletName()}</span>
|
||||
<button
|
||||
onClick={openWalletServiceProfile}
|
||||
className="text-sm font-medium hover:underline cursor-crosshair text-primary"
|
||||
>
|
||||
{getWalletName()}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Connection Status */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-muted-foreground">Status:</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={`size-2 rounded-full ${
|
||||
wallet ? "bg-green-500" : "bg-red-500"
|
||||
}`}
|
||||
/>
|
||||
<span className="text-sm font-medium">
|
||||
{wallet ? "Connected" : "Disconnected"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Lightning Address */}
|
||||
@@ -276,6 +306,8 @@ export default function UserMenu() {
|
||||
</DropdownMenuLabel>
|
||||
</DropdownMenuGroup>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
{/* Wallet Section */}
|
||||
{nwcConnection ? (
|
||||
<DropdownMenuItem
|
||||
@@ -283,7 +315,7 @@ export default function UserMenu() {
|
||||
onClick={() => setShowWalletInfo(true)}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Zap className="size-4 text-yellow-500" />
|
||||
<Wallet className="size-4 text-muted-foreground" />
|
||||
{balance !== undefined ||
|
||||
nwcConnection.balance !== undefined ? (
|
||||
<span className="text-sm">
|
||||
@@ -291,9 +323,16 @@ export default function UserMenu() {
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{getWalletName()}
|
||||
</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span
|
||||
className={`size-1.5 rounded-full ${
|
||||
wallet ? "bg-green-500" : "bg-red-500"
|
||||
}`}
|
||||
/>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{getWalletName()}
|
||||
</span>
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
) : (
|
||||
<DropdownMenuItem
|
||||
|
||||
@@ -12,9 +12,13 @@ import db from "@/services/db";
|
||||
* - Pubkey changes while a fetch is in progress
|
||||
*
|
||||
* @param pubkey - The user's public key (hex)
|
||||
* @param relayHints - Optional relay URLs to try fetching from
|
||||
* @returns ProfileContent or undefined if loading/not found
|
||||
*/
|
||||
export function useProfile(pubkey?: string): ProfileContent | undefined {
|
||||
export function useProfile(
|
||||
pubkey?: string,
|
||||
relayHints?: string[],
|
||||
): ProfileContent | undefined {
|
||||
const [profile, setProfile] = useState<ProfileContent | undefined>();
|
||||
const abortControllerRef = useRef<AbortController | null>(null);
|
||||
|
||||
@@ -37,8 +41,12 @@ export function useProfile(pubkey?: string): ProfileContent | undefined {
|
||||
}
|
||||
});
|
||||
|
||||
// Fetch from network
|
||||
const sub = profileLoader({ kind: kinds.Metadata, pubkey }).subscribe({
|
||||
// Fetch from network with optional relay hints
|
||||
const sub = profileLoader({
|
||||
kind: kinds.Metadata,
|
||||
pubkey,
|
||||
...(relayHints && relayHints.length > 0 && { relays: relayHints }),
|
||||
}).subscribe({
|
||||
next: async (fetchedEvent) => {
|
||||
if (controller.signal.aborted) return;
|
||||
if (!fetchedEvent || !fetchedEvent.content) return;
|
||||
@@ -77,7 +85,7 @@ export function useProfile(pubkey?: string): ProfileContent | undefined {
|
||||
controller.abort();
|
||||
sub.unsubscribe();
|
||||
};
|
||||
}, [pubkey]);
|
||||
}, [pubkey, relayHints]);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user