mirror of
https://github.com/aljazceru/rabbit.git
synced 2025-12-17 14:04:21 +01:00
83 lines
2.1 KiB
TypeScript
83 lines
2.1 KiB
TypeScript
import { createSignal, createEffect, onCleanup } from 'solid-js';
|
|
import type { Event as NostrEvent, Filter, SubscriptionOptions } from 'nostr-tools';
|
|
import usePool from '@/nostr/usePool';
|
|
|
|
export type UseSubscriptionProps = {
|
|
relayUrls: string[];
|
|
filters: Filter[];
|
|
options?: SubscriptionOptions;
|
|
// subscribe not only stored events but also new events published after the subscription
|
|
// default is true
|
|
continuous?: boolean;
|
|
onEvent?: (event: NostrEvent) => void;
|
|
onEOSE?: () => void;
|
|
signal?: AbortSignal;
|
|
};
|
|
|
|
const sortEvents = (events: NostrEvent[]) =>
|
|
Array.from(events).sort((a, b) => b.created_at - a.created_at);
|
|
|
|
const useSubscription = (propsProvider: () => UseSubscriptionProps | null) => {
|
|
const pool = usePool();
|
|
const [events, setEvents] = createSignal<NostrEvent[]>([]);
|
|
|
|
createEffect(() => {
|
|
const props = propsProvider();
|
|
if (props == null) return;
|
|
|
|
const { relayUrls, filters, options, onEvent, onEOSE, continuous = true } = props;
|
|
|
|
const sub = pool().sub(relayUrls, filters, options);
|
|
let pushed = false;
|
|
let eose = false;
|
|
const storedEvents: NostrEvent[] = [];
|
|
|
|
sub.on('event', (event: NostrEvent) => {
|
|
if (onEvent != null) {
|
|
onEvent(event);
|
|
}
|
|
if (!eose) {
|
|
pushed = true;
|
|
storedEvents.push(event);
|
|
} else {
|
|
// いったん50件だけ保持
|
|
setEvents((prevEvents) => sortEvents([event, ...prevEvents].slice(0, 50)));
|
|
}
|
|
});
|
|
|
|
sub.on('eose', () => {
|
|
if (onEOSE != null) {
|
|
onEOSE();
|
|
}
|
|
|
|
eose = true;
|
|
setEvents(sortEvents(storedEvents));
|
|
|
|
if (!continuous) {
|
|
sub.unsub();
|
|
}
|
|
});
|
|
|
|
// avoid updating an array too rapidly while this is fetching stored events
|
|
const intervalId = setInterval(() => {
|
|
if (eose) {
|
|
clearInterval(intervalId);
|
|
return;
|
|
}
|
|
if (pushed) {
|
|
pushed = false;
|
|
setEvents(sortEvents(storedEvents));
|
|
}
|
|
}, 100);
|
|
|
|
onCleanup(() => {
|
|
sub.unsub();
|
|
clearInterval(intervalId);
|
|
});
|
|
});
|
|
|
|
return { events };
|
|
};
|
|
|
|
export default useSubscription;
|