- useDirectMessages: correct nip44 getConversationKey (Uint8Array) + finalizeEvent EventTemplate (remove pubkey/unused ephemeralPubkey/bytesToHex)
- Access current-user metadata via useCurrentUser() spread instead of user.metadata across ~10 files (rename to userMetadata where author metadata already bound)
- useCrewGoal: explicit UseQueryResult<CrewGoal|null> return type (fixes CrewForm/CrewTreasuryCard {} inference)
- New useCommentCounts hook; fix EventsPage/MapPage misuse of useComments(string[])
- CoachDetailPage: typed pget/pbool accessors for craft-specific union fields
- MapPage: shop entries include tags/category to satisfy SkateSpot
- SkateGlobe: read event.tags; LabPage: remove duplicate serviceType; LabCrewsStrip: add 'judging'
- Icon prop widened to accept style; ReportDialog subtype guard; SecuritySettings/TourCard/EventsPage comparisons; CashuWallet onClick; ConversationPage recipients; useLoggedInAccounts NLoginType import; LicensePage icon; TourDetailPage ZapButton target + real npub link; TestApp useSkateRelay
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
101 lines
No EOL
3.3 KiB
TypeScript
101 lines
No EOL
3.3 KiB
TypeScript
import { useNostr } from '@nostrify/react';
|
|
import { useNostrLogin, type NLoginType } from '@nostrify/react/login';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { NSchema as n, NostrEvent, NostrMetadata } from '@nostrify/nostrify';
|
|
|
|
export interface Account {
|
|
id: string;
|
|
pubkey: string;
|
|
event?: NostrEvent;
|
|
metadata: NostrMetadata;
|
|
}
|
|
|
|
// Fallback relays for fetching profile data
|
|
const FALLBACK_RELAYS = [
|
|
'wss://relay.damus.io',
|
|
'wss://nos.lol',
|
|
'wss://purplepag.es',
|
|
];
|
|
|
|
export function useLoggedInAccounts() {
|
|
const { nostr } = useNostr();
|
|
const { logins, setLogin, removeLogin } = useNostrLogin();
|
|
|
|
// Extract pubkey safely — works for both standard NLoginType and custom AmberLoginType
|
|
const getPubkey = (login: NLoginType): string | undefined => {
|
|
return (login as unknown as { pubkey?: string }).pubkey;
|
|
};
|
|
|
|
const loginPubkeys = logins.map(getPubkey).filter((p): p is string => !!p);
|
|
|
|
const { data: authors = [] } = useQuery({
|
|
queryKey: ['nostr', 'logins', logins.map((l) => l.id).join(';')],
|
|
queryFn: async ({ signal }) => {
|
|
if (logins.length === 0) return [];
|
|
if (loginPubkeys.length === 0) return [];
|
|
|
|
// Try primary relays first with longer timeout
|
|
let events: NostrEvent[] = [];
|
|
|
|
try {
|
|
events = await nostr.query(
|
|
[{ kinds: [0], authors: loginPubkeys }],
|
|
{ signal: AbortSignal.any([signal, AbortSignal.timeout(5000)]) },
|
|
);
|
|
} catch (error) {
|
|
console.warn('[useLoggedInAccounts] Primary relay query failed, trying fallback relays...');
|
|
}
|
|
|
|
// If no events found, try fallback relays
|
|
if (events.length === 0) {
|
|
try {
|
|
const fallbackGroup = nostr.group(FALLBACK_RELAYS);
|
|
events = await fallbackGroup.query(
|
|
[{ kinds: [0], authors: loginPubkeys }],
|
|
{ signal: AbortSignal.any([signal, AbortSignal.timeout(8000)]) },
|
|
);
|
|
if (events.length > 0) {
|
|
console.log('[useLoggedInAccounts] Found profile on fallback relays');
|
|
}
|
|
} catch (error) {
|
|
console.warn('[useLoggedInAccounts] Fallback relay query also failed:', error);
|
|
}
|
|
}
|
|
|
|
return logins.map((login): Account => {
|
|
const id = login.id;
|
|
const pubkey = getPubkey(login) ?? '';
|
|
const event = events.find((e) => e.pubkey === pubkey);
|
|
try {
|
|
const metadata = n.json().pipe(n.metadata()).parse(event?.content);
|
|
return { id, pubkey, metadata, event };
|
|
} catch {
|
|
return { id, pubkey, metadata: {}, event };
|
|
}
|
|
});
|
|
},
|
|
retry: 3,
|
|
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 10000),
|
|
staleTime: 30000, // Consider data fresh for 30 seconds
|
|
});
|
|
|
|
// Current user is the first login
|
|
const currentUser: Account | undefined = (() => {
|
|
const login = logins[0];
|
|
if (!login) return undefined;
|
|
const pubkey = getPubkey(login) ?? '';
|
|
const author = authors.find((a) => a.id === login.id);
|
|
return { metadata: {}, ...author, id: login.id, pubkey };
|
|
})();
|
|
|
|
// Other users are all logins except the current one
|
|
const otherUsers = (authors || []).slice(1) as Account[];
|
|
|
|
return {
|
|
authors,
|
|
currentUser,
|
|
otherUsers,
|
|
setLogin,
|
|
removeLogin,
|
|
};
|
|
} |