diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx
index d979155..667abbf 100644
--- a/src/pages/SettingsPage.tsx
+++ b/src/pages/SettingsPage.tsx
@@ -14,15 +14,12 @@ import { useQueryClient } from '@tanstack/react-query';
import { useNostr } from '@nostrify/react';
import { NSchema as n } from '@nostrify/nostrify';
import { useState } from 'react';
-
import { LoginArea } from '@/components/auth/LoginArea';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
-import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { useCurrentUser } from '@/hooks/useCurrentUser';
import { useAppContext } from '@/hooks/useAppContext';
import { toast } from '@/hooks/useToast';
-
+import { cn } from '@/lib/utils';
import {
User,
Palette,
@@ -39,665 +36,526 @@ import {
Database,
Package,
ChevronRight,
+ ChevronLeft,
} from 'lucide-react';
-// Fallback relays for fetching profile data
-const PROFILE_FALLBACK_RELAYS = [
- 'wss://purplepag.es',
- 'wss://relay.damus.io',
- 'wss://nos.lol',
-];
+// ─── Types ────────────────────────────────────────────────────────────────────
-function ProfileTab() {
+type Section =
+ | null
+ | 'profile'
+ | 'follows'
+ | 'nip05'
+ | 'security'
+ | 'mydata'
+ | 'language'
+ | 'appearance'
+ | 'relays'
+ | 'wallet'
+ | 'stash'
+ | 'advanced';
+
+// ─── Back header ──────────────────────────────────────────────────────────────
+
+function BackHeader({ title, onBack }: { title: string; onBack: () => void }) {
+ return (
+
+
+
{title}
+
+ );
+}
+
+// ─── Menu row ────────────────────────────────────────────────────────────────
+
+function MenuRow({
+ icon: Icon,
+ label,
+ sublabel,
+ iconColor,
+ iconBg,
+ onClick,
+ href,
+ badge,
+}: {
+ icon: React.ComponentType<{ className?: string }>;
+ label: string;
+ sublabel?: string;
+ iconColor: string;
+ iconBg: string;
+ onClick?: () => void;
+ href?: string;
+ badge?: string;
+}) {
+ const inner = (
+
+
+
+
+
+
{label}
+ {sublabel &&
{sublabel}
}
+
+ {badge && (
+
+ {badge}
+
+ )}
+
+
+ );
+
+ if (href) {
+ return {inner};
+ }
+
+ return ;
+}
+
+// ─── Menu group ───────────────────────────────────────────────────────────────
+
+function MenuGroup({ title, children }: { title: string; children: React.ReactNode }) {
+ return (
+
+
{title}
+
+ {children}
+
+
+ );
+}
+
+// ─── Profile sub-screen ───────────────────────────────────────────────────────
+
+const PROFILE_FALLBACK_RELAYS = ['wss://purplepag.es', 'wss://relay.damus.io', 'wss://nos.lol'];
+
+function ProfileScreen({ onBack }: { onBack: () => void }) {
const { user, metadata } = useCurrentUser();
const { nostr } = useNostr();
const queryClient = useQueryClient();
const [isRefreshing, setIsRefreshing] = useState(false);
- const handleRefreshProfile = async () => {
+ const handleRefresh = async () => {
if (!user) return;
-
setIsRefreshing(true);
- console.log('[ProfileTab] Manual refresh for pubkey:', user.pubkey.slice(0, 8) + '...');
-
try {
- // First invalidate the cache
queryClient.invalidateQueries({ queryKey: ['author', user.pubkey] });
-
- // Try main relays
- let events = await nostr.query(
- [{ kinds: [0], authors: [user.pubkey], limit: 1 }],
- { signal: AbortSignal.timeout(8000) }
- );
-
- console.log('[ProfileTab] Main relays returned', events.length, 'events');
-
- // If not found, try fallback relays
+ let events = await nostr.query([{ kinds: [0], authors: [user.pubkey], limit: 1 }], { signal: AbortSignal.timeout(8000) });
if (events.length === 0) {
- console.log('[ProfileTab] Trying fallback relays...');
- const fallbackGroup = nostr.group(PROFILE_FALLBACK_RELAYS);
- events = await fallbackGroup.query(
- [{ kinds: [0], authors: [user.pubkey], limit: 1 }],
- { signal: AbortSignal.timeout(8000) }
- );
- console.log('[ProfileTab] Fallback relays returned', events.length, 'events');
+ const fallback = nostr.group(PROFILE_FALLBACK_RELAYS);
+ events = await fallback.query([{ kinds: [0], authors: [user.pubkey], limit: 1 }], { signal: AbortSignal.timeout(8000) });
}
-
if (events.length > 0) {
- const event = events[0];
- try {
- const profileMetadata = n.json().pipe(n.metadata()).parse(event.content);
- queryClient.setQueryData(['author', user.pubkey], { metadata: profileMetadata, event });
- toast({
- title: 'Profile refreshed!',
- description: `Found profile: ${profileMetadata.name || 'unnamed'}`,
- });
- } catch {
- toast({
- title: 'Profile found',
- description: 'But metadata could not be parsed.',
- variant: 'destructive',
- });
- }
+ const profileMetadata = n.json().pipe(n.metadata()).parse(events[0].content);
+ queryClient.setQueryData(['author', user.pubkey], { metadata: profileMetadata, event: events[0] });
+ toast({ title: 'Profile refreshed!', description: `Found: ${profileMetadata.name || 'unnamed'}` });
} else {
- toast({
- title: 'Profile not found',
- description: 'Your profile (kind 0 event) was not found on any relay. You may need to publish it.',
- variant: 'destructive',
- });
+ toast({ title: 'Profile not found', description: 'Not found on any relay.', variant: 'destructive' });
}
- } catch (error) {
- console.error('[ProfileTab] Refresh failed:', error);
- toast({
- title: 'Refresh failed',
- description: 'Could not connect to relays. Check your internet connection.',
- variant: 'destructive',
- });
+ } catch {
+ toast({ title: 'Refresh failed', description: 'Could not connect to relays.', variant: 'destructive' });
} finally {
setIsRefreshing(false);
}
};
- if (!user) {
- return (
-
-
-
- Login Required
-
- Log in to edit your profile.
-
-
-
-
- );
- }
-
return (
-
- {/* Profile sync status - show if no metadata found */}
- {!metadata?.name && (
-
-
-
-
-
-
- Profile not loaded. Your profile data wasn't found on the configured relays.
- Try refreshing or make sure you've published your profile.
-
-
- Logged in as: {user.pubkey}
-
-
-