OpChan/packages/react/src/hooks/core/useUserDisplay.ts

93 lines
2.9 KiB
TypeScript
Raw Normal View History

2025-09-18 22:04:40 +05:30
import { EDisplayPreference, EVerificationStatus } from '@opchan/core';
2025-09-22 17:49:02 +05:30
import { useEffect, useState } from 'react';
2025-09-18 22:04:40 +05:30
import { useClient } from '../../contexts/ClientContext';
2025-09-22 17:49:02 +05:30
import { useIdentity } from '../../contexts/IdentityContext';
2025-09-18 17:02:11 +05:30
export interface UserDisplayInfo {
displayName: string;
callSign: string | null;
ensName: string | null;
ordinalDetails: string | null;
verificationLevel: EVerificationStatus;
displayPreference: EDisplayPreference | null;
isLoading: boolean;
error: string | null;
}
2025-09-18 22:04:40 +05:30
/**
* User display hook with caching and reactive updates
*/
2025-09-18 17:02:11 +05:30
export function useUserDisplay(address: string): UserDisplayInfo {
2025-09-18 22:04:40 +05:30
const client = useClient();
2025-09-22 17:49:02 +05:30
const { getIdentity, getDisplayName } = useIdentity();
2025-09-18 17:02:11 +05:30
const [displayInfo, setDisplayInfo] = useState<UserDisplayInfo>({
displayName: `${address.slice(0, 6)}...${address.slice(-4)}`,
callSign: null,
ensName: null,
ordinalDetails: null,
verificationLevel: EVerificationStatus.WALLET_UNCONNECTED,
displayPreference: null,
isLoading: true,
error: null,
});
2025-09-22 17:49:02 +05:30
// Subscribe via IdentityContext by relying on its internal listener
2025-09-18 22:04:40 +05:30
useEffect(() => {
2025-09-22 17:49:02 +05:30
let cancelled = false;
const prime = async () => {
if (!address) return;
2025-09-18 22:04:40 +05:30
try {
const identity = await client.userIdentityService.getUserIdentity(address);
2025-09-22 17:49:02 +05:30
if (cancelled) return;
2025-09-18 22:04:40 +05:30
if (identity) {
setDisplayInfo({
2025-09-22 17:49:02 +05:30
displayName: getDisplayName(address),
2025-09-18 22:04:40 +05:30
callSign: identity.callSign || null,
ensName: identity.ensName || null,
ordinalDetails: identity.ordinalDetails
? identity.ordinalDetails.ordinalDetails
: null,
verificationLevel: identity.verificationStatus,
displayPreference: identity.displayPreference || null,
isLoading: false,
error: null,
});
} else {
2025-09-22 17:49:02 +05:30
setDisplayInfo(prev => ({
...prev,
displayName: getDisplayName(address),
2025-09-18 22:04:40 +05:30
isLoading: false,
error: null,
2025-09-22 17:49:02 +05:30
}));
2025-09-18 22:04:40 +05:30
}
2025-09-18 17:02:11 +05:30
} catch (error) {
2025-09-22 17:49:02 +05:30
setDisplayInfo(prev => ({
...prev,
2025-09-18 17:02:11 +05:30
isLoading: false,
error: error instanceof Error ? error.message : 'Unknown error',
2025-09-22 17:49:02 +05:30
}));
2025-09-18 17:02:11 +05:30
}
};
2025-09-22 17:49:02 +05:30
prime();
return () => { cancelled = true; };
}, [address, client.userIdentityService, getDisplayName]);
2025-09-18 17:02:11 +05:30
2025-09-22 17:49:02 +05:30
// Reactively reflect IdentityContext cache changes
2025-09-18 22:04:40 +05:30
useEffect(() => {
2025-09-22 17:49:02 +05:30
if (!address) return;
const id = getIdentity(address);
if (!id) return;
setDisplayInfo(prev => ({
...prev,
displayName: getDisplayName(address),
callSign: id.callSign,
ensName: id.ensName,
ordinalDetails: id.ordinalDetails,
verificationLevel: id.verificationStatus,
isLoading: false,
error: null,
}));
}, [address, getIdentity, getDisplayName]);
2025-09-18 17:02:11 +05:30
return displayInfo;
}