diff --git a/packages/react-chat/src/components/Channels/Channels.tsx b/packages/react-chat/src/components/Channels/Channels.tsx index e2c653f3..b180200b 100644 --- a/packages/react-chat/src/components/Channels/Channels.tsx +++ b/packages/react-chat/src/components/Channels/Channels.tsx @@ -1,14 +1,13 @@ import React, { useEffect } from "react"; import styled from "styled-components"; +import { useMessengerContext } from "../../contexts/messengerProvider"; import { ChannelData } from "../../models/ChannelData"; import { EditIcon } from "../Icons/EditIcon"; import { Channel } from "./Channel"; interface ChannelsProps { - notifications: { [id: string]: number }; - clearNotifications: (id: string) => void; onCommunityClick: (val: ChannelData) => void; activeChannelId: string; channels: ChannelData[]; @@ -17,14 +16,14 @@ interface ChannelsProps { } export function Channels({ - notifications, onCommunityClick, - clearNotifications, activeChannelId, channels, membersList, setCreateChat, }: ChannelsProps) { + const { clearNotifications, notifications } = useMessengerContext(); + useEffect(() => { const channel = channels.find((channel) => channel.id === activeChannelId); if (channel) { diff --git a/packages/react-chat/src/components/Chat.tsx b/packages/react-chat/src/components/Chat.tsx index e4d1e923..b7f582bd 100644 --- a/packages/react-chat/src/components/Chat.tsx +++ b/packages/react-chat/src/components/Chat.tsx @@ -2,11 +2,10 @@ import React, { useEffect, useMemo, useState } from "react"; import { Identity } from "status-communities/dist/cjs"; import styled from "styled-components"; +import { useMessengerContext } from "../contexts/messengerProvider"; import { useNarrow } from "../contexts/narrowProvider"; -import { useMessenger } from "../hooks/messenger/useMessenger"; import { ChannelData } from "../models/ChannelData"; import { Metadata } from "../models/Metadata"; -import { Theme } from "../styles/themes"; import { uintToImgUrl } from "../utils/uintToImgUrl"; import { Channels } from "./Channels/Channels"; @@ -18,23 +17,20 @@ import { CommunityModal } from "./Modals/CommunityModal"; import { CommunitySkeleton } from "./Skeleton/CommunitySkeleton"; interface ChatProps { - theme: Theme; communityKey: string; fetchMetadata?: (url: string) => Promise; identity: Identity; + setActiveChannel: (channel: ChannelData) => void; + activeChannel: ChannelData; } export function Chat({ - theme, communityKey, fetchMetadata, identity, + setActiveChannel, + activeChannel, }: ChatProps) { - const [activeChannel, setActiveChannel] = useState({ - id: "", - name: "", - description: "", - }); const [showMembers, setShowMembers] = useState(true); const [showChannels, setShowChannels] = useState(true); const [membersList, setMembersList] = useState([]); @@ -42,21 +38,11 @@ export function Chat({ const narrow = useNarrow(); - const { - messenger, - messages, - sendMessage, - notifications, - clearNotifications, - loadPrevDay, - loadingMessages, - community, - contacts, - } = useMessenger(activeChannel?.id ?? "", communityKey, identity); - const [isModalVisible, setIsModalVisible] = useState(false); const showModal = () => setIsModalVisible(true); + const { community } = useMessengerContext(); + const communityData = useMemo(() => { if (community?.description) { return { @@ -103,8 +89,6 @@ export function Chat({ )} setActiveChannel(e)} activeChannelId={activeChannel?.id ?? ""} channels={channels} @@ -117,24 +101,15 @@ export function Chat({ {!createChat && ( setShowMembers(!showMembers)} showMembers={showMembers} community={communityData} showCommunity={!showChannels} - loadPrevDay={() => loadPrevDay(activeChannel.id)} onCommunityClick={showModal} fetchMetadata={fetchMetadata} - loadingMessages={loadingMessages} - clearNotifications={clearNotifications} channels={channels} membersList={membersList} setMembersList={setMembersList} @@ -144,7 +119,6 @@ export function Chat({ {showMembers && !narrow && !createChat && ( diff --git a/packages/react-chat/src/components/Chat/ChatBody.tsx b/packages/react-chat/src/components/Chat/ChatBody.tsx index 5d1fed51..4aa4b758 100644 --- a/packages/react-chat/src/components/Chat/ChatBody.tsx +++ b/packages/react-chat/src/components/Chat/ChatBody.tsx @@ -2,13 +2,11 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; import { Identity } from "status-communities/dist/cjs"; import styled from "styled-components"; +import { useMessengerContext } from "../../contexts/messengerProvider"; import { useNarrow } from "../../contexts/narrowProvider"; import { ChannelData } from "../../models/ChannelData"; -import { ChatMessage } from "../../models/ChatMessage"; import { CommunityData } from "../../models/CommunityData"; -import { Contact } from "../../models/Contact"; import { Metadata } from "../../models/Metadata"; -import { Theme } from "../../styles/themes"; import { Channel } from "../Channels/Channel"; import { EmptyChannel } from "../Channels/EmptyChannel"; import { Community } from "../Community"; @@ -24,24 +22,15 @@ import { ChatMessages } from "./ChatMessages"; interface ChatBodyProps { identity: Identity; - contacts: Contact[]; - theme: Theme; channel: ChannelData; community: CommunityData | undefined; - messenger: any; - messages: ChatMessage[]; - sendMessage: (text: string, image?: Uint8Array) => void; onClick: () => void; showMembers: boolean; showCommunity: boolean; - notifications: { [id: string]: number }; setActiveChannel: (val: ChannelData) => void; activeChannelId: string; - loadPrevDay: () => void; onCommunityClick: () => void; fetchMetadata?: (url: string) => Promise; - loadingMessages: boolean; - clearNotifications: (id: string) => void; channels: ChannelData[]; membersList: string[]; setMembersList: any; @@ -50,29 +39,21 @@ interface ChatBodyProps { export function ChatBody({ identity, - contacts, - theme, channel, community, - messenger, - messages, - sendMessage, onClick, showMembers, showCommunity, - notifications, setActiveChannel, activeChannelId, - loadPrevDay, onCommunityClick, fetchMetadata, - loadingMessages, - clearNotifications, channels, membersList, setMembersList, setCreateChat, }: ChatBodyProps) { + const { messenger, messages } = useMessengerContext(); const narrow = useNarrow(); const [showChannelsList, setShowChannelsList] = useState(false); const [showMembersList, setShowMembersList] = useState(false); @@ -143,9 +124,8 @@ export function ChatBody({ messenger && community ? ( ) : ( @@ -153,7 +133,7 @@ export function ChatBody({ ) : ( )} - + )} @@ -161,11 +141,9 @@ export function ChatBody({ @@ -173,7 +151,6 @@ export function ChatBody({ {showMembersList && narrow && ( - + )} diff --git a/packages/react-chat/src/components/Chat/ChatInput.tsx b/packages/react-chat/src/components/Chat/ChatInput.tsx index 8793c83d..5267a223 100644 --- a/packages/react-chat/src/components/Chat/ChatInput.tsx +++ b/packages/react-chat/src/components/Chat/ChatInput.tsx @@ -1,7 +1,8 @@ import { Picker } from "emoji-mart"; import React, { useCallback, useEffect, useMemo, useState } from "react"; -import styled from "styled-components"; +import styled, { useTheme } from "styled-components"; +import { useMessengerContext } from "../../contexts/messengerProvider"; import { useLow } from "../../contexts/narrowProvider"; import { lightTheme, Theme } from "../../styles/themes"; import { uintToImgUrl } from "../../utils/uintToImgUrl"; @@ -12,12 +13,9 @@ import { StickerIcon } from "../Icons/StickerIcon"; import "emoji-mart/css/emoji-mart.css"; import { Modal } from "../Modals/Modal"; -type ChatInputProps = { - theme: Theme; - addMessage: (message: string, image?: Uint8Array) => void; -}; - -export function ChatInput({ theme, addMessage }: ChatInputProps) { +export function ChatInput() { + const { sendMessage } = useMessengerContext(); + const theme = useTheme() as Theme; const [content, setContent] = useState(""); const [showEmoji, setShowEmoji] = useState(false); const [inputHeight, setInputHeight] = useState(40); @@ -61,7 +59,7 @@ export function ChatInput({ theme, addMessage }: ChatInputProps) { e.preventDefault(); (e.target as HTMLTextAreaElement).style.height = "40px"; setInputHeight(40); - addMessage(content, imageUint); + sendMessage(content, imageUint); setImageUint(undefined); setContent(""); } diff --git a/packages/react-chat/src/components/Chat/ChatMessages.tsx b/packages/react-chat/src/components/Chat/ChatMessages.tsx index 872ad548..bc1ab613 100644 --- a/packages/react-chat/src/components/Chat/ChatMessages.tsx +++ b/packages/react-chat/src/components/Chat/ChatMessages.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useMemo, useRef, useState } from "react"; import styled from "styled-components"; +import { useMessengerContext } from "../../contexts/messengerProvider"; import { ChatMessage } from "../../models/ChatMessage"; import { Metadata } from "../../models/Metadata"; import { equalDate } from "../../utils"; @@ -14,17 +15,16 @@ import { ChatMessageContent } from "./ChatMessageContent"; type ChatMessagesProps = { messages: ChatMessage[]; - loadPrevDay: () => void; + activeChannelId: string; fetchMetadata?: (url: string) => Promise; - loadingMessages: boolean; }; export function ChatMessages({ messages, - loadPrevDay, + activeChannelId, fetchMetadata, - loadingMessages, }: ChatMessagesProps) { + const { loadPrevDay, loadingMessages } = useMessengerContext(); const [scrollOnBot, setScrollOnBot] = useState(true); const ref = useRef(null); const today = useMemo(() => new Date(), []); @@ -40,7 +40,7 @@ export function ChatMessages({ (ref?.current?.clientHeight ?? 0) >= (ref?.current?.scrollHeight ?? 0) ) { setScrollOnBot(true); - loadPrevDay(); + loadPrevDay(activeChannelId); } } }, [messages, messages.length, loadingMessages]); @@ -49,7 +49,7 @@ export function ChatMessages({ const setScroll = () => { if (ref && ref.current) { if (ref.current.scrollTop <= 0) { - loadPrevDay(); + loadPrevDay(activeChannelId); } if ( ref.current.scrollTop + ref.current.clientHeight == diff --git a/packages/react-chat/src/components/ChatLoader.tsx b/packages/react-chat/src/components/ChatLoader.tsx index dd46609e..8b7659a2 100644 --- a/packages/react-chat/src/components/ChatLoader.tsx +++ b/packages/react-chat/src/components/ChatLoader.tsx @@ -1,33 +1,41 @@ import React, { useState } from "react"; import { Identity } from "status-communities/dist/cjs"; +import { MessengerProvider } from "../contexts/messengerProvider"; +import { ChannelData } from "../models/ChannelData"; import { Metadata } from "../models/Metadata"; -import { Theme } from "../styles/themes"; import { Chat } from "./Chat"; import { IdentityLoader } from "./Form/IdentityLoader"; interface ChatLoaderProps { - theme: Theme; communityKey: string; fetchMetadata?: (url: string) => Promise; } -export function ChatLoader({ - theme, - communityKey, - fetchMetadata, -}: ChatLoaderProps) { +export function ChatLoader({ communityKey, fetchMetadata }: ChatLoaderProps) { const [identity, setIdentity] = useState(undefined); + const [activeChannel, setActiveChannel] = useState({ + id: "", + name: "", + description: "", + }); if (identity) { return ( - + communityKey={communityKey} + activeChannel={activeChannel.id} + > + + ); } else { return ; diff --git a/packages/react-chat/src/components/Members/Members.tsx b/packages/react-chat/src/components/Members/Members.tsx index bfd28c3b..d5a33242 100644 --- a/packages/react-chat/src/components/Members/Members.tsx +++ b/packages/react-chat/src/components/Members/Members.tsx @@ -2,20 +2,16 @@ import React from "react"; import { Identity } from "status-communities/dist/cjs"; import styled from "styled-components"; -import { Contact } from "../../models/Contact"; - import { MembersList } from "./MembersList"; interface MembersProps { identity: Identity; - contacts: Contact[]; setShowChannels: (val: boolean) => void; setMembersList: any; } export function Members({ identity, - contacts, setShowChannels, setMembersList, }: MembersProps) { @@ -24,7 +20,6 @@ export function Members({ Members diff --git a/packages/react-chat/src/components/Members/MembersList.tsx b/packages/react-chat/src/components/Members/MembersList.tsx index 5888d92c..8d9b1625 100644 --- a/packages/react-chat/src/components/Members/MembersList.tsx +++ b/packages/react-chat/src/components/Members/MembersList.tsx @@ -3,14 +3,13 @@ import { Identity, utils } from "status-communities/dist/cjs"; import { bufToHex } from "status-communities/dist/cjs/utils"; import styled from "styled-components"; -import { Contact } from "../../models/Contact"; +import { useMessengerContext } from "../../contexts/messengerProvider"; import { UserIcon } from "../Icons/UserIcon"; import { Member, MemberData, MemberIcon } from "./Member"; interface MembersListProps { identity: Identity; - contacts: Contact[]; setShowChannels: (val: boolean) => void; setShowMembers?: (val: boolean) => void; setMembersList: any; @@ -18,11 +17,12 @@ interface MembersListProps { export function MembersList({ identity, - contacts, setShowChannels, setShowMembers, setMembersList, }: MembersListProps) { + const { contacts } = useMessengerContext(); + return ( diff --git a/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx b/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx index ce9f93ba..9c8869db 100644 --- a/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx +++ b/packages/react-chat/src/components/NarrowMode/NarrowChannels.tsx @@ -8,11 +8,9 @@ import { NarrowTopbar } from "./NarrowTopbar"; interface NarrowChannelsProps { community: string; - notifications: { [id: string]: number }; setActiveChannel: (val: ChannelData) => void; activeChannelId: string; setShowChannels: (val: boolean) => void; - clearNotifications: (id: string) => void; channels: ChannelData[]; membersList: string[]; setCreateChat: (val: boolean) => void; @@ -20,11 +18,9 @@ interface NarrowChannelsProps { export function NarrowChannels({ community, - notifications, setActiveChannel, activeChannelId, setShowChannels, - clearNotifications, channels, membersList, setCreateChat, @@ -33,8 +29,6 @@ export function NarrowChannels({ { setActiveChannel(e); setShowChannels(false); diff --git a/packages/react-chat/src/components/NarrowMode/NarrowMembers.tsx b/packages/react-chat/src/components/NarrowMode/NarrowMembers.tsx index 4e494f31..d8e77347 100644 --- a/packages/react-chat/src/components/NarrowMode/NarrowMembers.tsx +++ b/packages/react-chat/src/components/NarrowMode/NarrowMembers.tsx @@ -3,7 +3,6 @@ import { Identity } from "status-communities/dist/cjs"; import styled from "styled-components"; import { CommunityData } from "../../models/CommunityData"; -import { Contact } from "../../models/Contact"; import { MembersList } from "../Members/MembersList"; import { NarrowTopbar } from "./NarrowTopbar"; @@ -11,7 +10,6 @@ import { NarrowTopbar } from "./NarrowTopbar"; interface NarrowMembersProps { identity: Identity; community: CommunityData; - contacts: Contact[]; setShowChannels: (val: boolean) => void; setShowMembersList: (val: boolean) => void; setMembersList: any; @@ -20,7 +18,6 @@ interface NarrowMembersProps { export function NarrowMembers({ identity, community, - contacts, setShowChannels, setShowMembersList, setMembersList, @@ -30,7 +27,6 @@ export function NarrowMembers({ diff --git a/packages/react-chat/src/contexts/messengerProvider.tsx b/packages/react-chat/src/contexts/messengerProvider.tsx new file mode 100644 index 00000000..9f8285b2 --- /dev/null +++ b/packages/react-chat/src/contexts/messengerProvider.tsx @@ -0,0 +1,37 @@ +import React, { createContext, useContext } from "react"; +import { Identity } from "status-communities/dist/cjs"; + +import { MessengerType, useMessenger } from "../hooks/messenger/useMessenger"; + +const MessengerContext = createContext({ + messenger: undefined, + messages: [], + sendMessage: async () => undefined, + notifications: {}, + clearNotifications: () => undefined, + loadPrevDay: async () => undefined, + loadingMessages: false, + community: undefined, + contacts: [], +}); + +export function useMessengerContext() { + return useContext(MessengerContext); +} + +interface NarrowProviderProps { + children: React.ReactNode; + activeChannel: string; + communityKey?: string; + identity?: Identity; +} + +export function MessengerProvider({ + children, + activeChannel, + communityKey, + identity, +}: NarrowProviderProps) { + const messenger = useMessenger(activeChannel, communityKey, identity); + return ; +} diff --git a/packages/react-chat/src/hooks/messenger/useMessenger.ts b/packages/react-chat/src/hooks/messenger/useMessenger.ts index 76df6d09..fe6b09ee 100644 --- a/packages/react-chat/src/hooks/messenger/useMessenger.ts +++ b/packages/react-chat/src/hooks/messenger/useMessenger.ts @@ -7,6 +7,7 @@ import { Messenger, } from "status-communities/dist/cjs"; +import { ChatMessage } from "../../models/ChatMessage"; import { Contact } from "../../models/Contact"; import { createCommunity } from "../../utils/createCommunity"; import { createMessenger } from "../../utils/createMessenger"; @@ -14,10 +15,25 @@ import { createMessenger } from "../../utils/createMessenger"; import { useLoadPrevDay } from "./useLoadPrevDay"; import { useMessages } from "./useMessages"; +export type MessengerType = { + messenger: Messenger | undefined; + messages: ChatMessage[]; + sendMessage: ( + messageText?: string | undefined, + image?: Uint8Array | undefined + ) => Promise; + notifications: { [chatId: string]: number }; + clearNotifications: (id: string) => void; + loadPrevDay: (id: string) => Promise; + loadingMessages: boolean; + community: Community | undefined; + contacts: Contact[]; +}; + export function useMessenger( chatId: string, - communityKey: string, - identity: Identity + communityKey: string | undefined, + identity: Identity | undefined ) { const [messenger, setMessenger] = useState(undefined); @@ -26,7 +42,7 @@ export function useMessenger( }>({}); const contactsClass = useMemo(() => { - if (messenger) { + if (messenger && identity) { const newContacts = new Contacts( identity, messenger.waku, @@ -38,7 +54,7 @@ export function useMessenger( ); return newContacts; } - }, [messenger]); + }, [messenger, identity]); const contacts = useMemo(() => { const now = Date.now(); @@ -58,13 +74,15 @@ export function useMessenger( const { loadPrevDay, loadingMessages } = useLoadPrevDay(chatId, messenger); useEffect(() => { - createMessenger(identity).then((e) => { - setMessenger(e); - }); - }, []); + if (identity) { + createMessenger(identity).then((e) => { + setMessenger(e); + }); + } + }, [identity]); useEffect(() => { - if (messenger && contactsClass) { + if (messenger && contactsClass && communityKey) { createCommunity(communityKey, addMessage, messenger).then((e) => { setCommunity(e); });