fix: populate peers without waiting for an event (#230)

This commit is contained in:
Sasha 2023-04-22 01:04:39 +02:00 committed by GitHub
parent 700de9d740
commit e83dd13931
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 8 deletions

View File

@ -24,7 +24,11 @@ export default function MessageInput(props: Props) {
const onMessage = async () => { const onMessage = async () => {
if (props.sendMessage && inputText) { if (props.sendMessage && inputText) {
await props.sendMessage(inputText); try {
await props.sendMessage(inputText);
} catch (e) {
console.error(`Failed to send message: ${e}`);
}
setInputText(""); setInputText("");
} }
}; };
@ -36,6 +40,7 @@ export default function MessageInput(props: Props) {
const onKeyDown = async (event: KeyboardEvent<HTMLInputElement>) => { const onKeyDown = async (event: KeyboardEvent<HTMLInputElement>) => {
if ( if (
isActive &&
event.key === "Enter" && event.key === "Enter" &&
!event.altKey && !event.altKey &&
!event.ctrlKey && !event.ctrlKey &&
@ -63,7 +68,7 @@ export default function MessageInput(props: Props) {
> >
<Row align="center"> <Row align="center">
<Fill> <Fill>
<TextInput value={inputText} /> <TextInput />
</Fill> </Fill>
<Fit> <Fit>
<SendButton /> <SendButton />

View File

@ -1,11 +1,11 @@
import type { LightNode } from "@waku/interfaces"; import type { LightNode } from "@waku/interfaces";
import ChatList from "./ChatList"; import ChatList from "./ChatList";
import MessageInput from "./MessageInput"; import MessageInput from "./MessageInput";
import { useWaku, useContentPair, useLightPush, usePeers } from "@waku/react"; import { useWaku, useContentPair, useLightPush } from "@waku/react";
import { TitleBar } from "@livechat/ui-kit"; import { TitleBar } from "@livechat/ui-kit";
import { Message } from "./Message"; import { Message } from "./Message";
import { ChatMessage } from "./chat_message"; import { ChatMessage } from "./chat_message";
import { useNodePeers } from "./hooks"; import { useNodePeers, usePeers } from "./hooks";
interface Props { interface Props {
messages: Message[]; messages: Message[];

View File

@ -2,7 +2,11 @@ import React, { useEffect, useState } from "react";
import { generate } from "server-name-generator"; import { generate } from "server-name-generator";
import { Message } from "./Message"; import { Message } from "./Message";
import { Decoder } from "@waku/core/lib/message/version_0"; import { Decoder } from "@waku/core/lib/message/version_0";
import { LightNode, StoreQueryOptions } from "@waku/interfaces"; import type {
Peer,
PeerProtocolsChangeData,
} from "@libp2p/interface-peer-store";
import type { LightNode, StoreQueryOptions, Waku } from "@waku/interfaces";
import { useFilterMessages, useStoreMessages } from "@waku/react"; import { useFilterMessages, useStoreMessages } from "@waku/react";
@ -64,8 +68,7 @@ export const useNodePeers = (node: undefined | LightNode) => {
useEffect(() => { useEffect(() => {
if (!node) return; if (!node) return;
// Update store peer when new peer connected & identified const listener = async (evt: any) => {
node.libp2p.peerStore.addEventListener("change:protocols", async (evt) => {
const { peerId } = evt.detail; const { peerId } = evt.detail;
const tags = (await node.libp2p.peerStore.getTags(peerId)).map( const tags = (await node.libp2p.peerStore.getTags(peerId)).map(
(t) => t.name (t) => t.name
@ -75,7 +78,13 @@ export const useNodePeers = (node: undefined | LightNode) => {
} else { } else {
setBootstrapPeers((peers) => new Set(peers).add(peerId.toString())); setBootstrapPeers((peers) => new Set(peers).add(peerId.toString()));
} }
}); };
// Update store peer when new peer connected & identified
node.libp2p.peerStore.addEventListener("change:protocols", listener);
return () => {
node.libp2p.peerStore.removeEventListener("change:protocols", listener);
};
}, [node]); }, [node]);
useEffect(() => { useEffect(() => {
@ -91,3 +100,67 @@ export const useNodePeers = (node: undefined | LightNode) => {
peerExchangePeers, peerExchangePeers,
}; };
}; };
type UsePeersParams = {
node: undefined | Waku;
};
type UsePeersResults = {
storePeers?: undefined | Peer[];
filterPeers?: undefined | Peer[];
lightPushPeers?: undefined | Peer[];
peerExchangePeers?: undefined | Peer[];
};
/**
* Hook returns map of peers for different protocols.
* If protocol is not implemented on the node peers are undefined.
* @example
* const { storePeers } = usePeers({ node });
* @param {Waku} params.node - Waku node, if not set then no peers will be returned
* @returns {Object} map of peers, if some of the protocols is not implemented then undefined
*/
export const usePeers = (params: UsePeersParams): UsePeersResults => {
const { node } = params;
const [peers, setPeers] = React.useState<UsePeersResults>({});
React.useEffect(() => {
if (!node) {
return;
}
const listener = async (_event?: CustomEvent<PeerProtocolsChangeData>) => {
const peers = await Promise.all([
handleCatch(node?.store?.peers()),
handleCatch(node?.filter?.peers()),
handleCatch(node?.lightPush?.peers()),
handleCatch(node?.peerExchange?.peers()),
]);
setPeers({
storePeers: peers[0],
filterPeers: peers[1],
lightPushPeers: peers[2],
peerExchangePeers: peers[3],
});
};
listener(); // populate peers before event is invoked
node.libp2p.peerStore.addEventListener("change:protocols", listener);
return () => {
node.libp2p.peerStore.removeEventListener("change:protocols", listener);
};
}, [node, setPeers]);
return peers;
};
function handleCatch(promise?: Promise<Peer[]>): Promise<Peer[] | undefined> {
if (!promise) {
return Promise.resolve(undefined);
}
return promise.catch((_) => {
return undefined;
});
}