mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
* context for storing subchain config and tx view for subchain * address page and block page for subchain * address aggregated page: local txs tab * connect MultichainSelect to context * home page placeholder * refactor subchain select state * envs for demo * fix ts * clear value for l2 review * subchain widgets on home page * csp policies * sockets, duck and goose * fix socket on subchain address page * link builder for subchain views * update home widget * fix time increment * enable tx interpretator and metadata service * generate multichain config based on every chain app config * Fix the multichain config to work in Docker * multichain socket test * rename subchain-id to subchain-slug path param * refactoring * update chain icons on entities * home page: latest local txs * latest cross-chain txs * minor improvements * renaming, pt. 1 * rename chain routes * enable blockchain interaction * add loading state to icon shield * fix build * fix tests * update types package
86 lines
2.4 KiB
TypeScript
86 lines
2.4 KiB
TypeScript
import type { Channel } from 'phoenix';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
|
|
import { useSocket } from './context';
|
|
|
|
interface Params {
|
|
topic: string | undefined;
|
|
params?: object;
|
|
isDisabled: boolean;
|
|
onJoin?: (channel: Channel, message: unknown) => void;
|
|
onSocketClose?: () => void;
|
|
onSocketError?: () => void;
|
|
}
|
|
|
|
export default function useSocketChannel({ topic, params, isDisabled, onJoin, onSocketClose, onSocketError }: Params) {
|
|
const { socket, channelRegistry } = useSocket() || {};
|
|
const [ channel, setChannel ] = useState<Channel>();
|
|
const onCloseRef = useRef<string>(undefined);
|
|
const onErrorRef = useRef<string>(undefined);
|
|
|
|
const onJoinRef = useRef(onJoin);
|
|
onJoinRef.current = onJoin;
|
|
|
|
useEffect(() => {
|
|
const cleanUpRefs = () => {
|
|
const refs = [ onCloseRef.current, onErrorRef.current ].filter(Boolean);
|
|
refs.length > 0 && socket?.off(refs);
|
|
};
|
|
|
|
if (!isDisabled) {
|
|
onCloseRef.current = onSocketClose && socket?.onClose(onSocketClose);
|
|
onErrorRef.current = onSocketError && socket?.onError(onSocketError);
|
|
} else {
|
|
cleanUpRefs();
|
|
}
|
|
|
|
return cleanUpRefs;
|
|
}, [ onSocketClose, onSocketError, socket, isDisabled ]);
|
|
|
|
useEffect(() => {
|
|
if (isDisabled && channel) {
|
|
channel.leave();
|
|
setChannel(undefined);
|
|
}
|
|
}, [ channel, isDisabled ]);
|
|
|
|
useEffect(() => {
|
|
if (!socket || isDisabled || !topic || !channelRegistry) {
|
|
return;
|
|
}
|
|
|
|
let ch: Channel;
|
|
if (channelRegistry.current[topic]) {
|
|
ch = channelRegistry.current[topic].channel;
|
|
channelRegistry.current[topic].subscribers++;
|
|
onJoinRef.current?.(ch, '');
|
|
} else {
|
|
ch = socket.channel(topic);
|
|
channelRegistry.current[topic] = { channel: ch, subscribers: 1 };
|
|
ch.join()
|
|
.receive('ok', (message) => onJoinRef.current?.(ch, message))
|
|
.receive('error', () => {
|
|
onSocketError?.();
|
|
});
|
|
}
|
|
|
|
setChannel(ch);
|
|
|
|
const currentRegistry = channelRegistry.current;
|
|
|
|
return () => {
|
|
if (currentRegistry[topic]) {
|
|
currentRegistry[topic].subscribers > 0 && currentRegistry[topic].subscribers--;
|
|
if (currentRegistry[topic].subscribers === 0) {
|
|
ch.leave();
|
|
delete currentRegistry[topic];
|
|
}
|
|
}
|
|
|
|
setChannel(undefined);
|
|
};
|
|
}, [ socket, topic, params, isDisabled, onSocketError, channelRegistry ]);
|
|
|
|
return channel;
|
|
}
|