Improve use messenger (#18)
This commit is contained in:
parent
c9246acd1e
commit
c07d912c39
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { ChannelData, channels } from "../helpers/channelsMock";
|
||||
|
@ -8,6 +8,8 @@ interface ChannelsProps {
|
|||
theme: Theme;
|
||||
icon: string;
|
||||
name: string;
|
||||
notifications: { [id: string]: number };
|
||||
clearNotifications: (id: string) => void;
|
||||
members: number;
|
||||
setActiveChannel: (val: ChannelData) => void;
|
||||
activeChannelId: number;
|
||||
|
@ -18,9 +20,20 @@ export function Channels({
|
|||
icon,
|
||||
name,
|
||||
members,
|
||||
notifications,
|
||||
setActiveChannel,
|
||||
clearNotifications,
|
||||
activeChannelId,
|
||||
}: ChannelsProps) {
|
||||
useEffect(() => {
|
||||
const channel = channels.find((channel) => channel.id === activeChannelId);
|
||||
if (channel) {
|
||||
if (notifications[channel.name] > 0) {
|
||||
clearNotifications(channel.name);
|
||||
}
|
||||
}
|
||||
}, [notifications, activeChannelId]);
|
||||
|
||||
return (
|
||||
<ChannelsWrapper theme={theme}>
|
||||
<Community>
|
||||
|
@ -37,6 +50,11 @@ export function Channels({
|
|||
channel={channel}
|
||||
theme={theme}
|
||||
isActive={channel.id === activeChannelId}
|
||||
notification={
|
||||
notifications[channel.name] > 0
|
||||
? notifications[channel.name]
|
||||
: undefined
|
||||
}
|
||||
onClick={() => {
|
||||
setActiveChannel(channel);
|
||||
}}
|
||||
|
@ -50,6 +68,7 @@ export function Channels({
|
|||
interface ChannelProps {
|
||||
theme: Theme;
|
||||
channel: ChannelData;
|
||||
notification?: number;
|
||||
isActive: boolean;
|
||||
activeView?: boolean;
|
||||
onClick?: () => void;
|
||||
|
@ -61,6 +80,7 @@ export function Channel({
|
|||
isActive,
|
||||
activeView,
|
||||
onClick,
|
||||
notification,
|
||||
}: ChannelProps) {
|
||||
return (
|
||||
<ChannelWrapper
|
||||
|
@ -82,7 +102,11 @@ export function Channel({
|
|||
<ChannelName
|
||||
theme={theme}
|
||||
className={
|
||||
isActive ? "active" : channel.notifications ? "notified" : ""
|
||||
isActive
|
||||
? "active"
|
||||
: notification && notification > 0
|
||||
? "notified"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
# {channel.name}
|
||||
|
@ -95,10 +119,8 @@ export function Channel({
|
|||
)}
|
||||
</ChannelTextInfo>
|
||||
</ChannelInfo>
|
||||
{channel.notifications && !activeView && (
|
||||
<NotificationBagde theme={theme}>
|
||||
{channel.notifications}
|
||||
</NotificationBagde>
|
||||
{notification && notification > 0 && !activeView && (
|
||||
<NotificationBagde theme={theme}>{notification}</NotificationBagde>
|
||||
)}
|
||||
</ChannelWrapper>
|
||||
);
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, { useState } from "react";
|
|||
import styled from "styled-components";
|
||||
|
||||
import { ChannelData, channels } from "../helpers/channelsMock";
|
||||
import { useMessenger } from "../hooks/useMessenger";
|
||||
import { Theme } from "../styles/themes";
|
||||
|
||||
import { Channels } from "./Channels";
|
||||
|
@ -16,11 +17,23 @@ interface ChatProps {
|
|||
|
||||
export function Chat({ theme, channelsON, membersON }: ChatProps) {
|
||||
const [activeChannel, setActiveChannel] = useState<ChannelData>(channels[0]);
|
||||
const {
|
||||
messenger,
|
||||
messages,
|
||||
sendMessage,
|
||||
notifications,
|
||||
clearNotifications,
|
||||
} = useMessenger(
|
||||
activeChannel.name,
|
||||
channels.map((channel) => channel.name)
|
||||
);
|
||||
|
||||
return (
|
||||
<ChatWrapper>
|
||||
{channelsON && (
|
||||
<Channels
|
||||
notifications={notifications}
|
||||
clearNotifications={clearNotifications}
|
||||
theme={theme}
|
||||
icon={"https://www.cryptokitties.co/icons/logo.svg"}
|
||||
name={"CryptoKitties"}
|
||||
|
@ -29,12 +42,31 @@ export function Chat({ theme, channelsON, membersON }: ChatProps) {
|
|||
activeChannelId={activeChannel.id}
|
||||
/>
|
||||
)}
|
||||
<ChatBody theme={theme} channel={activeChannel} />
|
||||
{messenger ? (
|
||||
<ChatBody
|
||||
theme={theme}
|
||||
channel={activeChannel}
|
||||
messages={messages}
|
||||
sendMessage={sendMessage}
|
||||
/>
|
||||
) : (
|
||||
<Loading>Connecting to waku</Loading>
|
||||
)}
|
||||
{membersON && <Members theme={theme} />}
|
||||
</ChatWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
const Loading = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const ChatWrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from "react";
|
|||
import styled from "styled-components";
|
||||
|
||||
import { ChannelData } from "../../helpers/channelsMock";
|
||||
import { useMessenger } from "../../hooks/useMessenger";
|
||||
import { ChatMessage } from "../../models/ChatMessage";
|
||||
import { Theme } from "../../styles/themes";
|
||||
import { Channel } from "../Channels";
|
||||
|
||||
|
@ -12,11 +12,16 @@ import { ChatMessages } from "./ChatMessages";
|
|||
interface ChatBodyProps {
|
||||
theme: Theme;
|
||||
channel: ChannelData;
|
||||
messages: ChatMessage[];
|
||||
sendMessage: (text: string) => void;
|
||||
}
|
||||
|
||||
export function ChatBody({ theme, channel }: ChatBodyProps) {
|
||||
const { messages, sendMessage } = useMessenger(channel.name);
|
||||
|
||||
export function ChatBody({
|
||||
theme,
|
||||
channel,
|
||||
messages,
|
||||
sendMessage,
|
||||
}: ChatBodyProps) {
|
||||
return (
|
||||
<ChatBodyWrapper theme={theme}>
|
||||
<ChannelWrapper>
|
||||
|
|
|
@ -1,17 +1,29 @@
|
|||
import { StoreCodec } from "js-waku";
|
||||
// import { StoreCodec } from "js-waku";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { Identity, Messenger } from "status-communities/dist/cjs";
|
||||
|
||||
import { ChatMessage } from "../models/ChatMessage";
|
||||
|
||||
export function useMessenger(chatId: string) {
|
||||
export function useMessenger(chatId: string, chatIdList: string[]) {
|
||||
const [messenger, setMessenger] = useState<Messenger | undefined>(undefined);
|
||||
const [messages, setMessages] = useState<{ [chatId: string]: ChatMessage[] }>(
|
||||
{}
|
||||
);
|
||||
const [notifications, setNotifications] = useState<{
|
||||
[chatId: string]: number;
|
||||
}>({});
|
||||
|
||||
const clearNotifications = useCallback((id: string) => {
|
||||
setNotifications((prevNotifications) => {
|
||||
return {
|
||||
...prevNotifications,
|
||||
[id]: 0,
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
const addNewMessage = useCallback(
|
||||
(sender: Uint8Array, content: string, date: Date) => {
|
||||
(sender: Uint8Array, content: string, date: Date, id: string) => {
|
||||
let signer = "0x";
|
||||
sender.forEach((e) => {
|
||||
signer = signer + e.toString(16);
|
||||
|
@ -22,87 +34,76 @@ export function useMessenger(chatId: string) {
|
|||
content: content,
|
||||
date: date,
|
||||
};
|
||||
return {
|
||||
...prevMessages,
|
||||
[chatId]: [...prevMessages[chatId], newMessage],
|
||||
};
|
||||
if (prevMessages?.[id]) {
|
||||
return {
|
||||
...prevMessages,
|
||||
[id]: [...prevMessages[id], newMessage],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...prevMessages,
|
||||
[id]: [newMessage],
|
||||
};
|
||||
}
|
||||
});
|
||||
if (chatId != id) {
|
||||
setNotifications((prevNotifications) => {
|
||||
return {
|
||||
...prevNotifications,
|
||||
[id]: prevNotifications[id] + 1,
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
[chatId]
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const createMessenger = async () => {
|
||||
const identity = Identity.generate();
|
||||
const messenger = await Messenger.create(identity);
|
||||
await new Promise((resolve) => {
|
||||
messenger.waku?.libp2p.peerStore.on(
|
||||
"change:protocols",
|
||||
({ protocols }) => {
|
||||
if (protocols.includes(StoreCodec)) {
|
||||
resolve("");
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
await messenger.joinChat(chatId);
|
||||
setMessages((prevMessages) => {
|
||||
return { ...prevMessages, [chatId]: [] };
|
||||
});
|
||||
const chat = messenger.chatsById.get(chatId);
|
||||
const contentTopic = chat?.contentTopic;
|
||||
|
||||
if (contentTopic) {
|
||||
const messages = await messenger.waku.store.queryHistory(
|
||||
[contentTopic],
|
||||
{ decryptionKeys: [chat?.symKey] }
|
||||
);
|
||||
console.log(messages);
|
||||
}
|
||||
messenger.addObserver((message) => {
|
||||
addNewMessage(
|
||||
message.signer ?? new Uint8Array(),
|
||||
message.chatMessage?.text ?? "",
|
||||
new Date(message.chatMessage?.proto.timestamp ?? 0)
|
||||
);
|
||||
}, chatId);
|
||||
await new Promise((resolve) =>
|
||||
messenger.waku.libp2p.pubsub.once("pubsub:subscription-change", () =>
|
||||
resolve(null)
|
||||
)
|
||||
);
|
||||
await Promise.all(
|
||||
chatIdList.map(async (id) => {
|
||||
await messenger.joinChat(id);
|
||||
clearNotifications(id);
|
||||
messenger.addObserver((message) => {
|
||||
addNewMessage(
|
||||
message.signer ?? new Uint8Array(),
|
||||
message.chatMessage?.text ?? "",
|
||||
new Date(message.chatMessage?.proto.timestamp ?? 0),
|
||||
id
|
||||
);
|
||||
}, id);
|
||||
})
|
||||
);
|
||||
setMessenger(messenger);
|
||||
};
|
||||
createMessenger();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const joinNewChat = async () => {
|
||||
try {
|
||||
await messenger?.joinChat(chatId);
|
||||
setMessages((prevMessages) => {
|
||||
return { ...prevMessages, [chatId]: [] };
|
||||
});
|
||||
messenger?.addObserver((message) => {
|
||||
addNewMessage(
|
||||
message.signer ?? new Uint8Array(),
|
||||
message.chatMessage?.text ?? "",
|
||||
new Date(message.chatMessage?.proto.timestamp ?? 0)
|
||||
);
|
||||
}, chatId);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
};
|
||||
joinNewChat();
|
||||
}, [chatId]);
|
||||
|
||||
const sendMessage = useCallback(
|
||||
async (messageText: string) => {
|
||||
await messenger?.sendMessage(messageText, chatId);
|
||||
addNewMessage(
|
||||
messenger?.identity.publicKey ?? new Uint8Array(),
|
||||
messageText,
|
||||
new Date()
|
||||
new Date(),
|
||||
chatId
|
||||
);
|
||||
},
|
||||
[chatId, messenger]
|
||||
);
|
||||
|
||||
return { messenger, messages: messages?.[chatId] ?? [], sendMessage };
|
||||
return {
|
||||
messenger,
|
||||
messages: messages?.[chatId] ?? [],
|
||||
sendMessage,
|
||||
notifications,
|
||||
clearNotifications,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue