diff --git a/packages/react-chat-example/src/index.tsx b/packages/react-chat-example/src/index.tsx index 469f6b3b..4bcde45e 100644 --- a/packages/react-chat-example/src/index.tsx +++ b/packages/react-chat-example/src/index.tsx @@ -1,4 +1,4 @@ -import { community, lightTheme, ReactChat } from "@dappconnect/react-chat"; +import { lightTheme, ReactChat } from "@dappconnect/react-chat"; import React, { useRef, useState } from "react"; import ReactDOM from "react-dom"; import styled from "styled-components"; @@ -65,7 +65,9 @@ function DragDiv() { diff --git a/packages/react-chat/src/components/Channels/Channels.tsx b/packages/react-chat/src/components/Channels/Channels.tsx index ac91ea87..f8968302 100644 --- a/packages/react-chat/src/components/Channels/Channels.tsx +++ b/packages/react-chat/src/components/Channels/Channels.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from "react"; import styled from "styled-components"; -import { ChannelData, channels } from "../../helpers/channelsMock"; +import { ChannelData } from "../../helpers/channelsMock"; import { Channel } from "./Channel"; @@ -9,7 +9,8 @@ interface ChannelsProps { notifications: { [id: string]: number }; clearNotifications: (id: string) => void; onCommunityClick: (val: ChannelData) => void; - activeChannelId: number; + activeChannelId: string; + channels: ChannelData[]; } export function Channels({ @@ -17,6 +18,7 @@ export function Channels({ onCommunityClick, clearNotifications, activeChannelId, + channels, }: ChannelsProps) { useEffect(() => { const channel = channels.find((channel) => channel.id === activeChannelId); diff --git a/packages/react-chat/src/components/Chat.tsx b/packages/react-chat/src/components/Chat.tsx index 9886b7ac..4072fa30 100644 --- a/packages/react-chat/src/components/Chat.tsx +++ b/packages/react-chat/src/components/Chat.tsx @@ -1,9 +1,9 @@ -import React, { useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import styled from "styled-components"; import { useNarrow } from "../contexts/narrowProvider"; -import { ChannelData, channels } from "../helpers/channelsMock"; -import { CommunityData } from "../helpers/communityMock"; +import { ChannelData } from "../helpers/channelsMock"; +import { uintToImgUrl } from "../helpers/uintToImgUrl"; import { useMessenger } from "../hooks/useMessenger"; import { Metadata } from "../models/Metadata"; import { Theme } from "../styles/themes"; @@ -16,12 +16,16 @@ import { CommunityModal } from "./Modals/CommunityModal"; interface ChatProps { theme: Theme; - community: CommunityData; + communityKey: string; fetchMetadata?: (url: string) => Promise; } -export function Chat({ theme, community, fetchMetadata }: ChatProps) { - const [activeChannel, setActiveChannel] = useState(channels[0]); +export function Chat({ theme, communityKey, fetchMetadata }: ChatProps) { + const [activeChannel, setActiveChannel] = useState({ + id: "", + name: "", + description: "", + }); const [showMembers, setShowMembers] = useState(true); const [showChannels, setShowChannels] = useState(true); const narrow = useNarrow(); @@ -34,24 +38,67 @@ export function Chat({ theme, community, fetchMetadata }: ChatProps) { clearNotifications, loadNextDay, loadingMessages, - } = useMessenger( - activeChannel.name, - channels.map((channel) => channel.name) - ); + community, + } = useMessenger(activeChannel?.id ?? "", communityKey); const [isModalVisible, setIsModalVisible] = useState(false); const showModal = () => setIsModalVisible(true); + const communityData = useMemo(() => { + if (community?.description) { + return { + id: 1, + name: community.description.identity?.displayName ?? "", + icon: uintToImgUrl( + community.description?.identity?.images?.thumbnail.payload ?? + new Uint8Array() + ), + members: 0, + membersList: [], + description: community.description.identity?.description ?? "", + }; + } else { + return { + id: 1, + name: "", + icon: "", + members: 0, + membersList: [], + description: "", + }; + } + }, [community]); + + const channels = useMemo(() => { + console.log(community?.chats); + if (community?.chats) { + return Array.from(community.chats.values()).map((chat) => { + return { + id: chat.id, + name: chat.communityChat?.identity?.displayName ?? "", + description: chat.communityChat?.identity?.description ?? "", + }; + }); + } else { + return []; + } + }, [community]); + + useEffect(() => { + if (channels.length > 0) setActiveChannel(channels[0]); + }, [channels]); + return ( {showChannels && !narrow && ( - + setActiveChannel(e)} - activeChannelId={activeChannel.id} + activeChannelId={activeChannel?.id ?? ""} + channels={channels} /> )} @@ -66,25 +113,26 @@ export function Chat({ theme, community, fetchMetadata }: ChatProps) { activeChannelId={activeChannel.id} onClick={() => setShowMembers(!showMembers)} showMembers={showMembers} - community={community} + community={communityData} showCommunity={!showChannels} loadNextDay={() => loadNextDay(activeChannel.name)} onCommunityClick={showModal} fetchMetadata={fetchMetadata} loadingMessages={loadingMessages} clearNotifications={clearNotifications} + channels={channels} /> {showMembers && !narrow && ( - + )} setIsModalVisible(false)} - icon={community.icon} - name={community.name} + icon={communityData.icon} + name={communityData.name} subtitle="Public Community" - description={community.description} - publicKey="0xD95DBdaB08A9FED2D71ac9C3028AAc40905d8CF3" + description={communityData.description} + publicKey={communityKey} /> ); diff --git a/packages/react-chat/src/components/Chat/ChatBody.tsx b/packages/react-chat/src/components/Chat/ChatBody.tsx index 1656d50e..cfcd26bc 100644 --- a/packages/react-chat/src/components/Chat/ChatBody.tsx +++ b/packages/react-chat/src/components/Chat/ChatBody.tsx @@ -31,12 +31,13 @@ interface ChatBodyProps { showCommunity: boolean; notifications: { [id: string]: number }; setActiveChannel: (val: ChannelData) => void; - activeChannelId: number; + activeChannelId: string; loadNextDay: () => void; onCommunityClick: () => void; fetchMetadata?: (url: string) => Promise; loadingMessages: boolean; clearNotifications: (id: string) => void; + channels: ChannelData[]; } export function ChatBody({ @@ -57,6 +58,7 @@ export function ChatBody({ fetchMetadata, loadingMessages, clearNotifications, + channels, }: ChatBodyProps) { const narrow = useNarrow(); const [showChannelsList, setShowChannelsList] = useState(false); @@ -137,6 +139,7 @@ export function ChatBody({ {showChannelsList && narrow && ( void; - activeChannelId: number; + activeChannelId: string; setShowChannels: (val: boolean) => void; clearNotifications: (id: string) => void; + channels: ChannelData[]; } export function NarrowChannels({ @@ -22,6 +23,7 @@ export function NarrowChannels({ activeChannelId, setShowChannels, clearNotifications, + channels, }: NarrowChannelsProps) { return ( @@ -34,6 +36,7 @@ export function NarrowChannels({ setShowChannels(false); }} activeChannelId={activeChannelId} + channels={channels} /> ); diff --git a/packages/react-chat/src/components/ReactChat.tsx b/packages/react-chat/src/components/ReactChat.tsx index 54fa2729..26c927c8 100644 --- a/packages/react-chat/src/components/ReactChat.tsx +++ b/packages/react-chat/src/components/ReactChat.tsx @@ -3,7 +3,6 @@ import { ThemeProvider } from "styled-components"; import styled from "styled-components"; import { NarrowProvider } from "../contexts/narrowProvider"; -import { CommunityData } from "../helpers/communityMock"; import { Metadata } from "../models/Metadata"; import { GlobalStyle } from "../styles/GlobalStyle"; import { Theme } from "../styles/themes"; @@ -12,11 +11,15 @@ import { Chat } from "./Chat"; interface ReactChatProps { theme: Theme; - community: CommunityData; + communityKey: string; fetchMetadata?: (url: string) => Promise; } -export function ReactChat({ theme, community, fetchMetadata }: ReactChatProps) { +export function ReactChat({ + theme, + communityKey, + fetchMetadata, +}: ReactChatProps) { const ref = useRef(null); return ( @@ -24,7 +27,7 @@ export function ReactChat({ theme, community, fetchMetadata }: ReactChatProps) { diff --git a/packages/react-chat/src/helpers/channelsMock.ts b/packages/react-chat/src/helpers/channelsMock.ts index 8044a44b..afe85504 100644 --- a/packages/react-chat/src/helpers/channelsMock.ts +++ b/packages/react-chat/src/helpers/channelsMock.ts @@ -1,9 +1,8 @@ export type ChannelData = { - id: number; + id: string; name: string; description: string; icon?: string; - notifications?: number; isMuted?: boolean; }; diff --git a/packages/react-chat/src/hooks/useMessenger.ts b/packages/react-chat/src/hooks/useMessenger.ts index 5a690979..0aa9aa18 100644 --- a/packages/react-chat/src/hooks/useMessenger.ts +++ b/packages/react-chat/src/hooks/useMessenger.ts @@ -1,7 +1,7 @@ // import { StoreCodec } from "js-waku"; import { StoreCodec } from "js-waku"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { Identity, Messenger } from "status-communities/dist/cjs"; +import { Community, Identity, Messenger } from "status-communities/dist/cjs"; import { ApplicationMetadataMessage } from "status-communities/dist/cjs"; import { uintToImgUrl } from "../helpers/uintToImgUrl"; @@ -32,11 +32,12 @@ function binarySetInsert( return arr; } -export function useMessenger(chatId: string, chatIdList: string[]) { +export function useMessenger(chatId: string, communityKey: string) { const [messenger, setMessenger] = useState(undefined); const [messages, setMessages] = useState<{ [chatId: string]: ChatMessage[] }>( {} ); + const [community, setCommunity] = useState(undefined); const [notifications, setNotifications] = useState<{ [chatId: string]: number; }>({}); @@ -105,7 +106,7 @@ export function useMessenger(chatId: string, chatIdList: string[]) { const loadNextDay = useCallback( async (id: string) => { if (messenger) { - const endTime = lastLoadTime.current[id]; + const endTime = lastLoadTime.current[id] ?? new Date(); const startTime = new Date(endTime.getTime() - _MS_PER_DAY); const timeDiff = Math.floor( (new Date().getTime() - endTime.getTime()) / _MS_PER_DAY @@ -139,6 +140,7 @@ export function useMessenger(chatId: string, chatIdList: string[]) { const createMessenger = async () => { // Test password for now // Need design for password input + let identity = await loadIdentity("test"); if (!identity) { identity = Identity.generate(); @@ -164,16 +166,20 @@ export function useMessenger(chatId: string, chatIdList: string[]) { } ); }); - + const community = await Community.instantiateCommunity( + communityKey, + messenger.waku + ); + setCommunity(community); await Promise.all( - chatIdList.map(async (id) => { - await messenger.joinChatById(id); - lastLoadTime.current[id] = new Date(); + Array.from(community.chats.values()).map(async (chat) => { + await messenger.joinChat(chat); + lastLoadTime.current[chat.id] = new Date(); messenger.addObserver( - (msg, date) => addNewMessage(msg, id, date), - id + (msg, date) => addNewMessage(msg, chat.id, date), + chat.id ); - clearNotifications(id); + clearNotifications(chat.id); }) ); setMessenger(messenger); @@ -182,8 +188,10 @@ export function useMessenger(chatId: string, chatIdList: string[]) { }, []); useEffect(() => { - if (messenger) { - chatIdList.forEach(loadNextDay); + if (messenger && community?.chats) { + Array.from(community?.chats.values()).forEach(({ id }) => + loadNextDay(id) + ); } }, [messenger]); @@ -224,5 +232,6 @@ export function useMessenger(chatId: string, chatIdList: string[]) { loadNextDay, lastMessage, loadingMessages, + community, }; }