mirror of
https://github.com/DocNR/POWR.git
synced 2025-04-23 01:01:27 +00:00
113 lines
2.9 KiB
TypeScript
113 lines
2.9 KiB
TypeScript
// lib/hooks/useSubscribe.ts
|
|
import { useEffect, useState, useRef } from 'react';
|
|
import { NDKFilter, NDKSubscription } from '@nostr-dev-kit/ndk';
|
|
import { NDKEvent, NDKUser } from '@nostr-dev-kit/ndk-mobile';
|
|
import { useNDK } from './useNDK';
|
|
|
|
interface UseSubscribeOptions {
|
|
enabled?: boolean;
|
|
closeOnEose?: boolean;
|
|
deduplicate?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Hook to subscribe to Nostr events
|
|
*
|
|
* @param filters The NDK filter or array of filters
|
|
* @param options Optional configuration options
|
|
* @returns Object containing events, loading state, and EOSE status
|
|
*/
|
|
export function useSubscribe(
|
|
filters: NDKFilter | NDKFilter[] | false,
|
|
options: UseSubscribeOptions = {}
|
|
) {
|
|
const { ndk } = useNDK();
|
|
const [events, setEvents] = useState<NDKEvent[]>([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [eose, setEose] = useState(false);
|
|
const subscriptionRef = useRef<NDKSubscription | null>(null);
|
|
|
|
// Default options
|
|
const {
|
|
enabled = true,
|
|
closeOnEose = false,
|
|
deduplicate = true
|
|
} = options;
|
|
|
|
useEffect(() => {
|
|
// Clean up previous subscription if exists
|
|
if (subscriptionRef.current) {
|
|
subscriptionRef.current.stop();
|
|
subscriptionRef.current = null;
|
|
}
|
|
|
|
// Reset state when filters change
|
|
setEvents([]);
|
|
setEose(false);
|
|
|
|
// Check prerequisites
|
|
if (!ndk || !filters || !enabled) {
|
|
setIsLoading(false);
|
|
return;
|
|
}
|
|
|
|
setIsLoading(true);
|
|
|
|
try {
|
|
// Convert single filter to array if needed
|
|
const filterArray = Array.isArray(filters) ? filters : [filters];
|
|
|
|
// Create subscription
|
|
const subscription = ndk.subscribe(filterArray);
|
|
subscriptionRef.current = subscription;
|
|
|
|
// Handle incoming events
|
|
subscription.on('event', (event: NDKEvent) => {
|
|
setEvents(prev => {
|
|
// Deduplicate events if enabled
|
|
if (deduplicate && prev.some(e => e.id === event.id)) {
|
|
return prev;
|
|
}
|
|
return [...prev, event];
|
|
});
|
|
});
|
|
|
|
// Handle end of stored events
|
|
subscription.on('eose', () => {
|
|
setIsLoading(false);
|
|
setEose(true);
|
|
|
|
if (closeOnEose && subscriptionRef.current) {
|
|
subscriptionRef.current.stop();
|
|
subscriptionRef.current = null;
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('[useSubscribe] Error:', error);
|
|
setIsLoading(false);
|
|
}
|
|
|
|
// Cleanup function
|
|
return () => {
|
|
if (subscriptionRef.current) {
|
|
subscriptionRef.current.stop();
|
|
subscriptionRef.current = null;
|
|
}
|
|
};
|
|
}, [ndk, enabled, closeOnEose, deduplicate, JSON.stringify(filters)]);
|
|
|
|
return {
|
|
events,
|
|
isLoading,
|
|
eose,
|
|
resubscribe: () => {
|
|
if (subscriptionRef.current) {
|
|
subscriptionRef.current.stop();
|
|
subscriptionRef.current = null;
|
|
}
|
|
setEvents([]);
|
|
setEose(false);
|
|
setIsLoading(true);
|
|
}
|
|
};
|
|
} |