add local messages, refactor code

This commit is contained in:
Sasha 2023-02-23 20:44:06 +01:00
parent 2bd10b2641
commit 2449e217dd
No known key found for this signature in database
5 changed files with 49 additions and 44 deletions

View File

@ -1,6 +1,3 @@
/* eslint no-use-before-define: 0 */
// @ts-ignore
import React, { useEffect, useState } from "react";
import "./App.css";
import handleCommand from "./command";
import Room from "./Room";
@ -19,7 +16,7 @@ const endTime = new Date();
export default function App() {
const { node } = useWaku<LightNode>();
const { decoder } = useContentPair();
const messages = useMessages({
const [messages, pushLocalMessages] = useMessages({
node,
decoder,
options: {
@ -34,23 +31,21 @@ export default function App() {
const [nick, setNick] = usePersistentNick();
const onCommand = (text: string): void => {
handleCommand(text, node, setNick).then(({ command, response }) => {
const commandMessages = response.map((msg) => {
return Message.fromUtf8String(command, msg);
});
pushLocalMessages(commandMessages);
});
};
return (
<div
className="chat-app"
style={{ height: "100vh", width: "100vw", overflow: "hidden" }}
>
<Room
nick={nick}
messages={messages}
commandHandler={(input: string) => {
handleCommand(input, node, setNick).then(({ command, response }) => {
const commandMessages = response.map((msg) => {
return Message.fromUtf8String(command, msg);
});
console.log("trying to send", commandMessages);
});
}}
/>
<Room nick={nick} messages={messages} commandHandler={onCommand} />
</div>
);
}

View File

@ -1,4 +1,4 @@
import { memo, useEffect, useRef } from "react";
import { useEffect, useRef } from "react";
import {
Message as LiveMessage,
MessageText,
@ -10,8 +10,6 @@ interface Props {
messages: Message[];
}
memo(ChatList);
export default function ChatList(props: Props) {
const renderedMessages = props.messages.map((message) => (
<LiveMessage

View File

@ -11,58 +11,54 @@ import {
} from "@livechat/ui-kit";
interface Props {
hasPeers: boolean;
sendMessage: ((msg: string) => Promise<void>) | undefined;
}
export default function MessageInput(props: Props) {
const [inputText, setInputText] = useState<string>("");
const [activeButton, setActiveButton] = useState<boolean>(false);
const { hasPeers } = props;
const { node } = useWaku<LightNode>();
const sendMessage = async () => {
const [inputText, setInputText] = useState<string>("");
const [isActive, setActiveButton] = useState<boolean>(false);
const onMessage = async () => {
if (props.sendMessage) {
await props.sendMessage(inputText);
setInputText("");
}
};
const messageHandler = (event: ChangeEvent<HTMLInputElement>) => {
const onChange = (event: ChangeEvent<HTMLInputElement>) => {
setInputText(event.target.value);
};
const keyPressHandler = async (event: KeyboardEvent<HTMLInputElement>) => {
const onKeyDown = async (event: KeyboardEvent<HTMLInputElement>) => {
if (
event.key === "Enter" &&
!event.altKey &&
!event.ctrlKey &&
!event.shiftKey
) {
await sendMessage();
await onMessage();
}
};
// Enable the button if there are peers available or the user is sending a command
useEffect(() => {
if (inputText.startsWith("/")) {
if (inputText.startsWith("/") || hasPeers) {
setActiveButton(true);
} else if (node) {
(async () => {
const peers = await node.lightPush.peers();
if (!!peers) {
setActiveButton(true);
} else {
setActiveButton(false);
}
})();
setActiveButton(false);
}
}, [activeButton, inputText, node]);
}, [inputText, hasPeers]);
return (
<TextComposer
onKeyDown={keyPressHandler}
onChange={messageHandler}
active={activeButton}
onButtonClick={sendMessage}
onKeyDown={onKeyDown}
onChange={onChange}
active={isActive}
onButtonClick={onMessage}
>
<Row align="center">
<Fill>

View File

@ -59,7 +59,7 @@ export default function Room(props: Props) {
title="Waku v2 chat app"
/>
<ChatList messages={props.messages} />
<MessageInput sendMessage={onSend} />
<MessageInput hasPeers={!!lightPushPeers} sendMessage={onSend} />
</div>
);
}

View File

@ -27,15 +27,31 @@ type UseMessagesParams = {
options: StoreQueryOptions;
};
export const useMessages = (params: UseMessagesParams): Message[] => {
type UseMessagesResult = [Message[], (v: Message[]) => void];
export const useMessages = (params: UseMessagesParams): UseMessagesResult => {
const { messages: newMessages } = useFilterMessages(params);
const { messages: storedMessages } = useStoreMessages(params);
const [localMessages, setLocalMessages] = useState<Message[]>([]);
return React.useMemo((): Message[] => {
const pushMessages = (msgs: Message[]) => {
if (!msgs || !msgs.length) {
return;
}
setLocalMessages((prev) => [...prev, ...msgs]);
};
const allMessages = React.useMemo((): Message[] => {
return [...storedMessages, ...newMessages]
.map(Message.fromWakuMessage)
.filter((v): v is Message => !!v);
}, [storedMessages, newMessages]);
.concat(localMessages)
.filter((v): v is Message => !!v)
.sort(
(left, right) => left.timestamp.getTime() - right.timestamp.getTime()
);
}, [storedMessages, newMessages, localMessages]);
return [allMessages, pushMessages];
};
export const useNodePeers = (node: undefined | LightNode) => {