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

99 lines
2.6 KiB
TypeScript
Raw Normal View History

2025-09-24 13:45:00 +05:30
import React from 'react';
import { useClient } from '../context/ClientContext';
2025-09-18 22:04:40 +05:30
import { EDisplayPreference, EVerificationStatus } from '@opchan/core';
2025-09-25 15:39:54 +05:30
import { UserIdentity } from '@opchan/core/dist/lib/services/UserIdentityService';
2025-09-18 17:02:11 +05:30
2025-09-25 15:39:54 +05:30
export interface UserDisplayInfo extends UserIdentity {
2025-09-18 17:02:11 +05:30
isLoading: boolean;
error: string | null;
}
2025-09-18 22:04:40 +05:30
/**
* User display hook with caching and reactive updates
2025-09-24 13:45:00 +05:30
* Takes an address and resolves display details for it
2025-09-18 22:04:40 +05:30
*/
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-24 13:45:00 +05:30
const [displayInfo, setDisplayInfo] = React.useState<UserDisplayInfo>({
2025-09-25 15:39:54 +05:30
address,
2025-09-18 17:02:11 +05:30
displayName: `${address.slice(0, 6)}...${address.slice(-4)}`,
2025-09-25 15:39:54 +05:30
lastUpdated: 0,
callSign: undefined,
ensName: undefined,
ordinalDetails: undefined,
verificationStatus: EVerificationStatus.WALLET_UNCONNECTED,
displayPreference: EDisplayPreference.WALLET_ADDRESS,
2025-09-18 17:02:11 +05:30
isLoading: true,
error: null,
});
2025-09-24 13:45:00 +05:30
// Initial load and refresh listener
React.useEffect(() => {
if (!address) return;
2025-09-22 17:49:02 +05:30
let cancelled = false;
2025-09-24 13:45:00 +05:30
const loadUserDisplay = async () => {
2025-09-18 22:04:40 +05:30
try {
2025-09-25 15:39:54 +05:30
const identity = await client.userIdentityService.getIdentity(address);
2025-09-24 13:45:00 +05:30
2025-09-22 17:49:02 +05:30
if (cancelled) return;
2025-09-24 13:45:00 +05:30
2025-09-18 22:04:40 +05:30
if (identity) {
setDisplayInfo({
2025-09-25 15:39:54 +05:30
...identity,
2025-09-18 22:04:40 +05:30
isLoading: false,
error: null,
});
}
2025-09-18 17:02:11 +05:30
} catch (error) {
2025-09-24 13:45:00 +05:30
if (cancelled) return;
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-24 13:45:00 +05:30
loadUserDisplay();
// Subscribe to identity service refresh events
2025-09-25 15:39:54 +05:30
const unsubscribe = client.userIdentityService.subscribe(async (changedAddress) => {
2025-09-24 13:45:00 +05:30
if (changedAddress !== address || cancelled) return;
try {
2025-09-25 15:39:54 +05:30
const identity = await client.userIdentityService.getIdentity(address);
2025-09-24 13:45:00 +05:30
if (!identity || cancelled) return;
setDisplayInfo(prev => ({
...prev,
2025-09-25 15:39:54 +05:30
...identity,
2025-09-24 13:45:00 +05:30
isLoading: false,
error: null,
}));
} catch (error) {
if (cancelled) return;
setDisplayInfo(prev => ({
...prev,
isLoading: false,
error: error instanceof Error ? error.message : 'Unknown error',
}));
}
2025-09-23 17:35:25 +05:30
});
2025-09-24 13:45:00 +05:30
return () => {
cancelled = true;
try {
unsubscribe();
} catch {
// Ignore unsubscribe errors
}
};
2025-09-25 15:39:54 +05:30
}, [address, client]);
2025-09-18 17:02:11 +05:30
return displayInfo;
2025-09-24 13:45:00 +05:30
}