From d35a432cb49d997d08e84b51fba2de5c8958e752 Mon Sep 17 00:00:00 2001 From: Abhishek <77395788+abhishek-01k@users.noreply.github.com> Date: Tue, 13 Feb 2024 13:20:59 +0530 Subject: [PATCH] upgraded push user for push chat (#1406) * upgraded push user for push chat * Moved chat user context to app context (#1412) * partial commit * added search and dynamic linking in chatpreviewlist * fixed dynamic link * added formatting for .wallet * Resolve verifier address issue * Console error and warning fix (#1390) * fixed button and chatviewlist warning * fixed memory leak in useeffect * Push admin address updated * added chat components * Added Collapsable Sidebar UI (#1410) * Sidebar Collapsable new UI and Logic (#1396) * Sidebar Collapsable new UI and Logic * Sidebar State persistant and Yield Farming logo done * Sidebar components are adjusted according to the design * Module width changes when collapsed * Fixed the margin of dashboard, send and yield modules * Removed the arrow in more button * changes according to code rules * Tooltip for collapsable sidebar * name change * changes --------- Co-authored-by: Abhishek <77395788+abhishek-01k@users.noreply.github.com> * modified 404 page not found page (#1405) * fixed button and chatviewlist warning * fixed memory leak in useeffect * modified 404 not found page in dapp * removed unnecessary styles * few tweaks --------- Co-authored-by: harshrajat * Moved ChatuserContext to AppContext * fixed reviw bugs * fixed a bug * fix: z-index of chat profile & chat preview load on big screen * Update user is fixed and restapi version updated * Read only mode active when user rejects signature * rejection toast is added and chat is ready for read mode --------- Co-authored-by: harshrajat Co-authored-by: Monalisha Mishra Co-authored-by: Nilesh Gupta Co-authored-by: Satyam <100528412+KlausMikhaelson@users.noreply.github.com> Co-authored-by: Monalisha Mishra <42746736+mishramonalisha76@users.noreply.github.com> Co-authored-by: Pritipriya Singh --------- Co-authored-by: harshrajat Co-authored-by: Monalisha Mishra Co-authored-by: Nilesh Gupta Co-authored-by: Satyam <100528412+KlausMikhaelson@users.noreply.github.com> Co-authored-by: Monalisha Mishra <42746736+mishramonalisha76@users.noreply.github.com> Co-authored-by: Pritipriya Singh --- package.json | 4 +- src/App.tsx | 10 +- .../chat/w2wChat/TypeBar/Typebar.tsx | 8 +- .../chat/w2wChat/chatBox/ChatBox.tsx | 118 +++-- src/components/chat/w2wChat/chatQR/chatQR.tsx | 4 +- .../chat/w2wChat/chatQR/mobileView.tsx | 10 +- .../createGroup/CreateGroupModalContent.tsx | 8 +- .../groupInfo/groupInfoModalContent.tsx | 8 +- .../chat/w2wChat/intentFeed/IntentFeed.tsx | 8 +- .../chat/w2wChat/messageFeed/MessageFeed.tsx | 8 +- .../chat/w2wChat/profile/Profile.tsx | 5 +- .../chat/w2wChat/searchBar/SearchBar.tsx | 247 +-------- src/components/video/IncomingCall.tsx | 4 +- src/components/video/OutgoingOngoingCall.tsx | 6 +- src/components/video/VideoPlayer.tsx | 9 +- src/contexts/AppContext.tsx | 257 ++++++++- src/contexts/ChatUserContext.tsx | 236 --------- src/contexts/VideoCallContext.tsx | 4 +- src/hooks/usePeer.ts | 91 ++-- src/index.js | 10 +- src/modules/chat/ChatModule.tsx | 487 ++++++++++-------- src/modules/space/SpaceModule.tsx | 20 +- src/primaries/Profile.tsx | 13 +- src/sections/chat/ChatSidebarSection.tsx | 357 ++++++++----- src/sections/space/SpaceFeedSection.tsx | 4 +- src/sections/video/VideoCallSection.tsx | 6 +- src/structure/MasterInterfacePage.tsx | 42 +- src/types/chat.ts | 20 +- src/types/context.ts | 60 ++- yarn.lock | 20 +- 30 files changed, 1046 insertions(+), 1038 deletions(-) delete mode 100644 src/contexts/ChatUserContext.tsx diff --git a/package.json b/package.json index ffd06b5534..dfab0eecc7 100644 --- a/package.json +++ b/package.json @@ -33,9 +33,9 @@ "@mui/icons-material": "^5.8.4", "@mui/lab": "^5.0.0-alpha.72", "@mui/material": "^5.5.0", - "@pushprotocol/restapi": "1.6.6", + "@pushprotocol/restapi": "0.0.1-alpha.64", "@pushprotocol/socket": "0.5.3", - "@pushprotocol/uiweb": "1.2.4", + "@pushprotocol/uiweb": "0.0.1-alpha.41", "@reduxjs/toolkit": "^1.7.1", "@testing-library/dom": "^9.0.1", "@testing-library/jest-dom": "^4.2.4", diff --git a/src/App.tsx b/src/App.tsx index 8281a1d3b7..6e6201d39f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -13,7 +13,7 @@ import { createGlobalStyle } from 'styled-components'; // Internal Compoonents import InitState from 'components/InitState'; -import AppContextProvider from 'contexts/AppContext'; +import AppContextProvider, { AppContext } from 'contexts/AppContext'; import NavigationContextProvider from 'contexts/NavigationContext'; import { useAccount, useInactiveListener, useSDKSocket } from 'hooks'; import { resetAdminSlice } from 'redux/slices/adminSlice'; @@ -35,7 +35,6 @@ import { setIndex, setRun, setWelcomeNotifsEmpty } from './redux/slices/userJour import { appConfig } from 'config'; import GLOBALS from 'config/Globals'; import { themeDark, themeLight } from 'config/Themization'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { GlobalContext } from 'contexts/GlobalContext'; // space imports @@ -113,6 +112,7 @@ if (appConfig?.appEnv === "prod") { } } + // Provess App export default function App() { const dispatch = useDispatch(); @@ -120,6 +120,7 @@ export default function App() { const { isActive, account, chainId, provider } = useAccount(); const [currentTime, setcurrentTime] = React.useState(0); const { authError, setAuthError } = useContext(ErrorContext); + const { pgpPvtKey } = useContext(AppContext); const { sidebarCollapsed, setSidebarCollapsed } = React.useContext(GlobalContext); const updateOnboardTheme = useUpdateTheme(); @@ -241,8 +242,6 @@ export default function App() { }; const librarySigner = provider?.getSigner(account); - const { pgpPvtKey } = useContext(ChatUserContext); - const spaceUI = useMemo(() => new SpacesUI({ account: account, @@ -260,7 +259,6 @@ export default function App() { return ( - {(!isActive || !allowedChain) && ( @@ -333,8 +331,6 @@ export default function App() { )} - - ); } diff --git a/src/components/chat/w2wChat/TypeBar/Typebar.tsx b/src/components/chat/w2wChat/TypeBar/Typebar.tsx index 0e1684bfda..c9f94a4ec8 100644 --- a/src/components/chat/w2wChat/TypeBar/Typebar.tsx +++ b/src/components/chat/w2wChat/TypeBar/Typebar.tsx @@ -10,16 +10,16 @@ import styled, { useTheme } from 'styled-components'; import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; import { ButtonV2, ItemHV2, SpanV2 } from 'components/reusables/SharedStylingV2'; import { Context } from 'modules/chat/ChatModule'; -import { AppContext } from 'types/chat'; +import { ChatUserAppContext } from 'types/chat'; import { FileMessageContent } from './Files/Files'; import GifPicker from './Gifs/GifPicker'; // Internal configs import { appConfig } from 'config'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { caip10ToWallet } from 'helpers/w2w'; import { MessagetypeType } from '../../../../types/chat'; import {filterXSS} from 'xss' +import { AppContext } from 'contexts/AppContext'; interface ITypeBar { @@ -48,8 +48,8 @@ const Typebar = ({ setSnackbarText, approveIntent, }: ITypeBar) => { - const { currentChat, activeTab, setChat }: AppContext = useContext(Context); - const {connectedUser} = useContext(ChatUserContext); + const { currentChat, activeTab, setChat }: ChatUserAppContext = useContext(Context); + const {connectedUser} = useContext(AppContext); const [showEmojis, setShowEmojis] = useState(false); const [isGifPickerOpened, setIsGifPickerOpened] = useState(false); const fileInputRef = useRef(null); diff --git a/src/components/chat/w2wChat/chatBox/ChatBox.tsx b/src/components/chat/w2wChat/chatBox/ChatBox.tsx index 21b2181619..c9e0c6a061 100644 --- a/src/components/chat/w2wChat/chatBox/ChatBox.tsx +++ b/src/components/chat/w2wChat/chatBox/ChatBox.tsx @@ -15,7 +15,7 @@ import ScrollToBottom from 'react-scroll-to-bottom'; import { useClickAway } from 'react-use'; import styled, { useTheme } from 'styled-components'; import { produce } from 'immer'; -import { ChatProfile, ChatViewList, MessageInput } from '@pushprotocol/uiweb'; +import { ChatProfile, ChatViewList, MessageInput, UserProfile } from '@pushprotocol/uiweb'; // Internal Components import { ReactComponent as Info } from 'assets/chat/group-chat/info.svg'; import { ReactComponent as InfoDark } from 'assets/chat/group-chat/infodark.svg'; @@ -26,7 +26,6 @@ import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderS import { ButtonV2, ImageV2, ItemHV2, ItemVV2, SpanV2 } from 'components/reusables/SharedStylingV2'; import Tooltip from 'components/reusables/tooltip/Tooltip'; import { Content } from 'components/SharedStyling'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { checkIfChatExist } from 'helpers/w2w/user'; import { useAccount, useDeviceWidthCheck } from 'hooks'; import { useResolveWeb3Name } from 'hooks/useResolveWeb3Name'; @@ -60,7 +59,7 @@ const Alert = React.forwardRef(function Alert(props, }); const ChatBox = ({ showGroupInfoModal }): JSX.Element => { - const { currentChat, viewChatBox, receivedIntents, activeTab, setChat }: ContextType = + const { currentChat, viewChatBox, receivedIntents, activeTab,setViewChatBox, setChat, selectedChatId }: ContextType = useContext(Context); const { web3NameList }: AppContextType = useContext(AppContext); @@ -72,13 +71,11 @@ const ChatBox = ({ showGroupInfoModal }): JSX.Element => { const [isGroup, setIsGroup] = useState(false); const [showGroupInfo, setShowGroupInfo] = useState(false); const groupInfoRef = useRef(null); - const { connectedUser } = useContext(ChatUserContext); + const { connectedUser } = useContext(AppContext); const { videoObject } = useContext(VideoCallContext); const theme = useTheme(); const isMobile = useDeviceWidthCheck(600); - - useClickAway(groupInfoRef, () => setShowGroupInfo(false)); //resolve web3 names @@ -87,7 +84,15 @@ const ChatBox = ({ showGroupInfoModal }): JSX.Element => { // get web3 name let ensName = ''; if (!isGroup && currentChat?.wallets?.split(',')[0].toString()) { - const walletLowercase = currentChat.wallets.includes(':nft') ? caip10ToWallet(currentChat?.wallets.replace(/eip155:\d+:/, 'eip155:').split(':nft')[0].toString().toLowerCase()) : caip10ToWallet(currentChat?.wallets?.split(',')[0].toString())?.toLowerCase(); + const walletLowercase = currentChat.wallets.includes(':nft') + ? caip10ToWallet( + currentChat?.wallets + .replace(/eip155:\d+:/, 'eip155:') + .split(':nft')[0] + .toString() + .toLowerCase() + ) + : caip10ToWallet(currentChat?.wallets?.split(',')[0].toString())?.toLowerCase(); const checksumWallet = ethers.utils.getAddress(walletLowercase); ensName = web3NameList[checksumWallet]; } @@ -107,7 +112,6 @@ const ChatBox = ({ showGroupInfoModal }): JSX.Element => { if (currentChat) { setIsGroup(checkIfGroup(currentChat)); - console.log('currentChat', checkIfGroup(currentChat), isGroup); // We only delete the messages once the user clicks on another chat. The user could click multiple times on the same chat and it would delete the previous messages // even though the user was still on the same chat. const image = getGroupImage(currentChat); @@ -121,17 +125,17 @@ const ChatBox = ({ showGroupInfoModal }): JSX.Element => { if (Loading) setLoading(false); }, [currentChat]); - const getDisplayName = () => { - if (ensName) return `${ensName} (${currentChat.wallets.includes(':nft') ? caip10ToWallet(currentChat?.wallets.replace(/eip155:\d+:/, 'eip155:').split(':nft')[0].toString().toLowerCase()) : caip10ToWallet(currentChat?.wallets?.split(',')[0].toString())?.toLowerCase()})`; - if (isGroup) - return isMobile - ? currentChat?.groupInformation?.groupName.length > 25 - ? currentChat?.groupInformation?.groupName?.slice(0, 25) + '...' - : currentChat?.groupInformation?.groupName - : currentChat?.groupInformation?.groupName; - if (currentChat?.wallets) return caip10ToWallet(currentChat.wallets.includes(':nft') ? currentChat?.wallets.replace(/eip155:\d+:/, 'eip155:').split(':nft')[0].toString().toLowerCase() : currentChat?.wallets?.split(',')[0].toString()?.toLowerCase()); + const getChatId = () => { + let chatId = selectedChatId || currentChat?.did; + if(chatId){ + return (chatId?.includes(':nft:') + ? chatId.replace(/eip155:\d+:/, 'eip155:').split(':nft')[0] + : chatId) ; + } + return chatId; + + }; - const handleCloseSuccessSnackbar = (event?: React.SyntheticEvent | Event, reason?: string): void => { if (reason === 'clickaway') { return; @@ -167,10 +171,9 @@ const ChatBox = ({ showGroupInfoModal }): JSX.Element => { { id: 7, content: 'Access to more chat requests and messages will be added in the near future' }, ]; - return ( - {!viewChatBox ? ( + {(!viewChatBox && !getChatId() )? ( {activeTab == 4 && ( { ) : ( <> - { background={theme.default.bg} padding="6px" fontWeight="500" - zIndex="99999" + zIndex="1" > - {(!!currentChat || !!Object.keys(currentChat || {}).length) && ( - - - - - } style="Info" chatId={(currentChat?.did?.includes(":") ? currentChat?.did.split(":")[1] : currentChat?.did) || currentChat?.groupInformation?.chatId} /> - - + {getChatId() && ( + setViewChatBox(false)}> + + + :null + } + chatProfileRightHelperComponent={ + + + + + + } + chatId={getChatId()} + /> )} - {(!!currentChat || !!Object.keys(currentChat || {}).length) && ( + {(getChatId()) && ( )} @@ -291,15 +302,16 @@ const ChatBox = ({ showGroupInfoModal }): JSX.Element => { {checkIfChatExist({ chats: receivedIntents, currentChat, connectedUser, isGroup }) ? null : ( <> - {(!!currentChat || !!Object.keys(currentChat || {}).length) && ( - - - + {getChatId() && ( + )} )} - )} @@ -317,7 +329,7 @@ const MessageInputWrapper = styled.div` justify-content: center; position: absolute; bottom: 8px; - z-index: 99; + `; const ChatContainer = styled.div` @@ -358,8 +370,6 @@ const MessageContainer = styled(ItemVV2)` @media (max-height: 400px) { height: 45%; } - - `; const GroupInfo = styled(ItemHV2)` diff --git a/src/components/chat/w2wChat/chatQR/chatQR.tsx b/src/components/chat/w2wChat/chatQR/chatQR.tsx index 391634ab6e..c804a00d42 100644 --- a/src/components/chat/w2wChat/chatQR/chatQR.tsx +++ b/src/components/chat/w2wChat/chatQR/chatQR.tsx @@ -9,9 +9,9 @@ import { AiOutlineClose, AiOutlineQrcode } from "react-icons/ai"; import { H2V2, ItemHV2, ItemVV2 } from "components/reusables/SharedStylingV2"; import GLOBALS, { device } from "config/Globals"; import BlurBG from "components/reusables/blurs/BlurBG"; -import { ChatUserContext } from "contexts/ChatUserContext"; import chatBoxImage from "../../../../assets/chat/chatBox.svg"; import { useAccount } from "hooks"; +import { AppContext } from "contexts/AppContext"; const ChatQR = ({ type = LOADER_TYPE.STANDALONE, @@ -21,7 +21,7 @@ const ChatQR = ({ }) => { const theme = useTheme(); const { account } = useAccount(); - const { createUserIfNecessary, displayQR, setDisplayQR, pgpPvtKey, connectedPeerID } = useContext(ChatUserContext); + const { pgpPvtKey,connectedPeerID,displayQR, setDisplayQR, createUserIfNecessary } = useContext(AppContext); const [myPeer, myPeerID] = usePeer(); const [qrCodeText, setQrCodeText] = useState(''); const [loading, setLoading] = useState(true); diff --git a/src/components/chat/w2wChat/chatQR/mobileView.tsx b/src/components/chat/w2wChat/chatQR/mobileView.tsx index cd5743e1ae..c14a767bf5 100644 --- a/src/components/chat/w2wChat/chatQR/mobileView.tsx +++ b/src/components/chat/w2wChat/chatQR/mobileView.tsx @@ -2,11 +2,11 @@ import BlurBG from 'components/reusables/blurs/BlurBG'; import { LOADER_OVERLAY, LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; import { ItemVV2 } from 'components/reusables/SharedStylingV2'; import GLOBALS, { device } from 'config/Globals'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import React, { useContext } from 'react'; import { AiOutlineClose, AiOutlineMore } from 'react-icons/ai'; import styled, { useTheme } from 'styled-components'; import backgroundImage from "../../../../assets/chat/QRBackground.svg"; +import { AppContext } from 'contexts/AppContext'; const MobileView = ({ type = LOADER_TYPE.STANDALONE, @@ -15,7 +15,13 @@ const MobileView = ({ width = 'auto' }) => { - const { createUserIfNecessary, displayQR, setDisplayQR, pgpPvtKey, connectedPeerID } = useContext(ChatUserContext); + const { + pgpPvtKey, + connectedPeerID, + displayQR, + setDisplayQR, + createUserIfNecessary + } = useContext(AppContext); const theme = useTheme(); return ( diff --git a/src/components/chat/w2wChat/groupChat/createGroup/CreateGroupModalContent.tsx b/src/components/chat/w2wChat/groupChat/createGroup/CreateGroupModalContent.tsx index 275f61b838..63e6b7fdbc 100644 --- a/src/components/chat/w2wChat/groupChat/createGroup/CreateGroupModalContent.tsx +++ b/src/components/chat/w2wChat/groupChat/createGroup/CreateGroupModalContent.tsx @@ -14,11 +14,10 @@ import { ReactComponent as Back } from 'assets/chat/arrowleft.svg'; import { GroupDetailsContent } from './GroupDetailsContent'; import { AddWalletContent } from './AddWalletContent'; import { ItemHV2, SpanV2 } from 'components/reusables/SharedStylingV2'; -import { ChatUserContext } from '../../../../../contexts/ChatUserContext'; import { appConfig } from '../../../../../config'; import useToast from 'hooks/useToast'; import { MdCheckCircle, MdError } from 'react-icons/md'; -import { AppContext, Feeds } from 'types/chat'; +import { ChatUserAppContext, Feeds } from 'types/chat'; import { Context } from 'modules/chat/ChatModule'; import { fetchInbox } from 'helpers/w2w/user'; import { profilePicture } from 'config/W2WConfig'; @@ -26,18 +25,19 @@ import { useAccount, useDeviceWidthCheck } from 'hooks'; import { device } from 'config/Globals'; import { CreateGroupModal } from "@pushprotocol/uiweb"; import { ChatUIProvider } from '@pushprotocol/uiweb'; +import { AppContext } from 'contexts/AppContext'; export const CreateGroupModalContent = ({ onClose, onConfirm: createGroup, toastObject }: ModalInnerComponentType) => { const [createGroupState, setCreateGroupState] = React.useState(1); - const { setInbox }: AppContext = useContext(Context); + const { setInbox }: ChatUserAppContext = useContext(Context); const [groupNameData, setGroupNameData] = React.useState(''); const [groupDescriptionData, setGroupDescriptionData] = React.useState(''); const [groupImageData, setGroupImageData] = React.useState(null); const [groupTypeObject, setGroupTypeObject] = React.useState(); const [isLoading, setIsLoading] = React.useState(false); const [memberList, setMemberList] = React.useState([]); - const { connectedUser, setConnectedUser , createUserIfNecessary} = useContext(ChatUserContext); + const { connectedUser, setConnectedUser, createUserIfNecessary } = useContext(AppContext); const {provider } = useAccount(); const themes = useTheme(); const createGroupToast = useToast(); diff --git a/src/components/chat/w2wChat/groupChat/groupInfo/groupInfoModalContent.tsx b/src/components/chat/w2wChat/groupChat/groupInfo/groupInfoModalContent.tsx index 16849fc1f7..d685e6f27d 100644 --- a/src/components/chat/w2wChat/groupChat/groupInfo/groupInfoModalContent.tsx +++ b/src/components/chat/w2wChat/groupChat/groupInfo/groupInfoModalContent.tsx @@ -14,10 +14,9 @@ import AddAdmin from 'assets/chat/group-chat/addadmin.svg'; import DismissAdmin from 'assets/chat/group-chat/dismissadmin.svg'; import Remove from 'assets/chat/group-chat/remove.svg'; import { ImageV2, ItemHV2, ItemVV2, SpanV2 } from 'components/reusables/SharedStylingV2'; -import { AppContext } from 'types/chat'; +import { ChatUserAppContext } from 'types/chat'; import { caip10ToWallet } from 'helpers/w2w'; import { Context } from 'modules/chat/ChatModule'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { ProfileCard } from './ProfileCard'; import { convertToWalletAddressList, @@ -38,10 +37,11 @@ import { MdCheckCircle, MdError } from 'react-icons/md'; import { AddWalletContent } from '../createGroup/AddWalletContent'; import GroupModalHeader from '../createGroup/GroupModalHeader'; import { copyToClipboard, shortenText } from 'helpers/UtilityHelper'; +import { AppContext } from 'contexts/AppContext'; export const GroupInfoModalContent = ({ onClose }: ModalInnerComponentType) => { - const { currentChat, setChat, inbox, receivedIntents }: AppContext = useContext(Context); - const { connectedUser } = useContext(ChatUserContext); + const { currentChat, setChat, inbox, receivedIntents }: ChatUserAppContext = useContext(Context); + const { connectedUser } = useContext(AppContext); const [copyText, setCopyText] = useState(''); const { account } = useAccount(); const groupInfoToast = useToast(); diff --git a/src/components/chat/w2wChat/intentFeed/IntentFeed.tsx b/src/components/chat/w2wChat/intentFeed/IntentFeed.tsx index 6d62fad966..a2fcb288fc 100644 --- a/src/components/chat/w2wChat/intentFeed/IntentFeed.tsx +++ b/src/components/chat/w2wChat/intentFeed/IntentFeed.tsx @@ -12,11 +12,11 @@ import ChatSnap from "components/chat/chatsnap/ChatSnap"; import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; import { ItemVV2, SpanV2 } from 'components/reusables/SharedStylingV2'; import { Context } from 'modules/chat/ChatModule'; -import { AppContext, Feeds } from 'types/chat'; +import { ChatUserAppContext, Feeds } from 'types/chat'; import { checkIfGroup, getChatsnapMessage, getGroupImage,getName, } from 'helpers/w2w/groupChat'; import { fetchIntent } from 'helpers/w2w/user'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { useAccount } from 'hooks'; +import { AppContext } from 'contexts/AppContext'; @@ -26,8 +26,8 @@ const IntentFeed = ({isLoading}): JSX.Element => { setChat, receivedIntents, setReceivedIntents - }: AppContext = useContext(Context); - const { connectedUser} = useContext(ChatUserContext); + }: ChatUserAppContext = useContext(Context); + const { connectedUser} = useContext(AppContext); const [selectedIntentSnap, setSelectedIntentSnap] = useState(); const { chainId, account } = useAccount(); const [limit, setLimit] = useState(10); diff --git a/src/components/chat/w2wChat/messageFeed/MessageFeed.tsx b/src/components/chat/w2wChat/messageFeed/MessageFeed.tsx index b10d8e0c5d..05031d2162 100644 --- a/src/components/chat/w2wChat/messageFeed/MessageFeed.tsx +++ b/src/components/chat/w2wChat/messageFeed/MessageFeed.tsx @@ -10,15 +10,15 @@ import { Waypoint } from 'react-waypoint'; import ChatSnap from 'components/chat/chatsnap/ChatSnap'; import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; import { ItemVV2, SpanV2 } from 'components/reusables/SharedStylingV2'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { decryptFeeds, walletToCAIP10 } from 'helpers/w2w'; import { fetchInbox, getDefaultGroupFeed } from 'helpers/w2w/user'; import useToast from 'hooks/useToast'; import { Context } from 'modules/chat/ChatModule'; -import { AppContext, Feeds, IGroup, User } from 'types/chat'; +import { ChatUserAppContext, Feeds, IGroup, User } from 'types/chat'; import { checkIfGroup, getChatsnapMessage, getGroupImage, getName } from '../../../../helpers/w2w/groupChat'; import { getDefaultFeed } from '../../../../helpers/w2w/user'; import { useAccount } from 'hooks'; +import { AppContext } from 'contexts/AppContext'; // Internal Configs @@ -32,9 +32,9 @@ interface MessageFeedPropsI { const MessageFeed = (props: MessageFeedPropsI): JSX.Element => { const theme = useTheme(); - const { setChat, setInbox, currentChat, receivedIntents, setActiveTab, activeTab, inbox, setHasUserBeenSearched, filteredUserData, setFilteredUserData }: AppContext = useContext(Context); + const { setChat, setInbox, currentChat, receivedIntents, setActiveTab, activeTab, inbox, setHasUserBeenSearched, filteredUserData, setFilteredUserData }: ChatUserAppContext = useContext(Context); - const { connectedUser } = useContext(ChatUserContext); + const { connectedUser } = useContext(AppContext); const [feeds, setFeeds] = useState([]); const [messagesLoading, setMessagesLoading] = useState(true); diff --git a/src/components/chat/w2wChat/profile/Profile.tsx b/src/components/chat/w2wChat/profile/Profile.tsx index b89d5aa52c..2968a1b07b 100644 --- a/src/components/chat/w2wChat/profile/Profile.tsx +++ b/src/components/chat/w2wChat/profile/Profile.tsx @@ -8,7 +8,6 @@ import styled, { useTheme } from 'styled-components'; // Internal Components import { ImageV2, ItemVV2, SpanV2 } from 'components/reusables/SharedStylingV2'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { AiOutlineMore } from 'react-icons/ai'; import { useResolveWeb3Name } from 'hooks/useResolveWeb3Name'; import { shortenText } from 'helpers/UtilityHelper'; @@ -17,14 +16,12 @@ import { AppContextType } from 'types/context'; import { useAccount } from 'hooks'; const Profile = ({ setActiveTab,showQR,setShowQR }: any): JSX.Element => { - const { web3NameList }:AppContextType=useContext(AppContext); + const { web3NameList,connectedUser }:AppContextType=useContext(AppContext); const { account } = useAccount() // theme context const theme = useTheme(); - const {connectedUser} = useContext(ChatUserContext); - // resolve web3 name useResolveWeb3Name(account); diff --git a/src/components/chat/w2wChat/searchBar/SearchBar.tsx b/src/components/chat/w2wChat/searchBar/SearchBar.tsx index b47a388c27..9adf5ec57a 100644 --- a/src/components/chat/w2wChat/searchBar/SearchBar.tsx +++ b/src/components/chat/w2wChat/searchBar/SearchBar.tsx @@ -1,63 +1,41 @@ // React + Web3 Essentials -import { Web3Provider } from '@ethersproject/providers'; -import { ethers } from 'ethers'; + import React, { useContext, useEffect, useRef, useState } from 'react'; // External Packages import CloseIcon from '@material-ui/icons/Close'; import AddIcon from '@mui/icons-material/Add'; -import { MdError } from 'react-icons/md'; import styled, { useTheme } from 'styled-components'; // Internal Components -import * as PushAPI from "@pushprotocol/restapi"; import { ReactComponent as SearchIcon } from 'assets/chat/search.svg'; import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; import { ButtonV2, ImageV2, ItemHV2, ItemVV2, SpanV2 } from 'components/reusables/SharedStylingV2'; -import { appConfig } from 'config'; -import { findObject } from 'helpers/UtilityHelper'; -import * as w2wChatHelper from 'helpers/w2w'; -import { displayDefaultUser } from 'helpers/w2w/user'; -import useToast from 'hooks/useToast'; import { Context } from 'modules/chat/ChatModule'; -import { getGroup } from 'services/chats/getGroup'; -import { getGroupbyChatId } from 'services/chats/getGroupByChatId'; -import { getGroupByName } from 'services/chats/getGroupByName'; -import { AppContext, IGroup, User } from 'types/chat'; +import { AppContext } from 'types/chat'; import ArrowLeft from '../../../../assets/chat/arrowleft.svg'; -import MessageFeed from '../messageFeed/MessageFeed'; -import { getUdResolver } from 'helpers/w2w/udResolver'; -const SearchBar = ({ autofilled }) => { + +const SearchBar = ({ autofilled, searchedUser, setSearchedUser }) => { // get theme const theme = useTheme(); const { - hasUserBeenSearched, setHasUserBeenSearched, activeTab, setActiveTab, userShouldBeSearched, setUserShouldBeSearched, - filteredUserData, - setFilteredUserData, - inbox, }: AppContext = useContext(Context); - const [searchedUser, setSearchedUser] = useState(''); - const [isInValidAddress, setIsInvalidAddress] = useState(false); + const [isLoadingSearch, setIsLoadingSearch] = useState(false); - const provider = new ethers.providers.InfuraProvider(appConfig.coreContractChain, appConfig.infuraAPIKey); - const udResolver = getUdResolver(); - const searchFeedToast = useToast(); - if (autofilled) { - // console.log("Search is autofilled:", autofilled); - } + useEffect(() => { if (searchedUser !== '' && userShouldBeSearched) { - handleSearch(); + setSearchedUser(searchedUser); setUserShouldBeSearched(false); } return () => setUserShouldBeSearched(false); @@ -65,39 +43,20 @@ const SearchBar = ({ autofilled }) => { useEffect(() => { if (autofilled && !userShouldBeSearched) { - // automate search - // setSearchedUser(autofilled); - - // const event = new KeyboardEvent('keypress', { - // key: 'enter', - // }); - // console.log("in search") - submitSearch(null, autofilled); + + if (autofilled.includes('chatid')) { + setSearchedUser(autofilled.split(':')[1]); + } else { + setSearchedUser(autofilled); + } + submitSearch(); } }, [userShouldBeSearched, autofilled]); - useEffect(() => { - if (isInValidAddress) { - searchFeedToast.showMessageToast({ - toastTitle: 'Error', - toastMessage: 'Invalid Search', - toastType: 'ERROR', - getToastIcon: (size) => ( - - ), - }); - - if (activeTab == 4) { - setActiveTab(0); - } - } - }, [isInValidAddress]); const onChangeSearchBox = async (event: React.ChangeEvent): Promise => { let searchAddress = event.target.value; + if (searchAddress === '') { clearInput(); } else { @@ -105,150 +64,13 @@ const SearchBar = ({ autofilled }) => { } }; - const submitSearch = (event: React.FormEvent | null, autoSearch: string = null): void => { - if (autoSearch) { - //!There is a case when the user enter a wallet Address less than the fixed length of the wallet address - if (autoSearch.includes('chatid')) { - handleSearch(autoSearch.split(':')[1]); - } - else { - handleSearch(autoSearch); - } - - } else { - //!There is a case when the user enter a wallet Address less than the fixed length of the wallet address - event.preventDefault(); - handleSearch(); - } - - }; - - const setInvalidSearch = () => { - setIsInvalidAddress(true); - setFilteredUserData([]); - setHasUserBeenSearched(true); - } - const handleSearch = async (autoSearch: string = null): Promise => { - let searchText = autoSearch ? autoSearch : searchedUser; - setIsInvalidAddress(false); - - if (!ethers.utils.isAddress(searchText)) { - setIsLoadingSearch(true); - let address: string; - let group: IGroup; - - if (searchText.includes('.')) { - try { - // address = await provider.resolveName(searchText); - // if (!address) { - // address = await library.resolveName(searchText); - // } - - address = - (await provider.resolveName(searchText)) || - // (await library.resolveName(searchText)) || - (await udResolver.owner(searchText)); - - - } catch (err) { - setInvalidSearch(); - } - } - else { - group = await getGroup(searchText, setInvalidSearch); - } - - // this ensures address are checksummed + const submitSearch = (): void => { - if (address) { - address = ethers.utils.getAddress(address?.toLowerCase()); - handleUserSearch({ userSearchData: address }); - } else if (group) { - handleUserSearch({ groupSearchData: group }); - } - else if (!group && !address) { - setInvalidSearch(); - } - } else { - await handleUserSearch({ userSearchData: searchText }); - } - setIsLoadingSearch(false); + setActiveTab(3); }; - //this function needs some optimisation - const handleUserSearch = async ({ userSearchData, groupSearchData }: { userSearchData?: string, groupSearchData?: IGroup }): Promise => { - setIsLoadingSearch(true); - let filteredData: User; - setHasUserBeenSearched(true); - - if (userSearchData) { - const caip10 = w2wChatHelper.walletToCAIP10({ account: userSearchData }); - filteredData = await PushAPI.user.get({ - account: caip10, - env: appConfig.appEnv - }); - // Checking whether user already present in contact list - let isUserConnected = findObject(filteredData, inbox, 'did'); - - if (filteredData !== null && isUserConnected) { - if (activeTab !== 0) { - setUserShouldBeSearched(true); - if (autofilled) { - setActiveTab(4); - } else { - setActiveTab(0); - } - } - setFilteredUserData([filteredData]); - setSearchedUser(''); - } else if (ethers.utils.isAddress(userSearchData)) { - setUserShouldBeSearched(true); - if (autofilled) { - setActiveTab(4); - } else { - setActiveTab(3); - } - const displayUser = displayDefaultUser({ caip10 }); - setFilteredUserData([displayUser]); - setSearchedUser(''); - } else { - setIsInvalidAddress(true); - setFilteredUserData([]); - } - // User is not in the protocol. Create new user - } else { - if (groupSearchData) { - const isGroupInInbox = inbox.find((inb) => inb?.groupInformation?.chatId === groupSearchData.chatId); - if (isGroupInInbox) { - if (activeTab != 0) { - setUserShouldBeSearched(true); - //check if in inbox - if (autofilled) { - setActiveTab(4); - } else { - setActiveTab(3); - } - } - } else { - setUserShouldBeSearched(true); - //check if in inbox - if (autofilled) { - setActiveTab(4); - } else { - setActiveTab(3); - } - } - setFilteredUserData([groupSearchData]); - setSearchedUser(''); - } else { - setIsInvalidAddress(true); - setFilteredUserData([]); - } - } - }; const clearInput = (): void => { - setFilteredUserData([]); setSearchedUser(''); setHasUserBeenSearched(false); setIsLoadingSearch(false); @@ -296,9 +118,10 @@ const SearchBar = ({ autofilled }) => { alignItems="stretch" display={activeTab == 4 ? 'none' : 'flex'} > - + e.key === 'Enter'? submitSearch():null} value={searchedUser} onChange={onChangeSearchBox} placeholder="Search Web3 domain or 0x123..." @@ -333,12 +156,12 @@ const SearchBar = ({ autofilled }) => { )} {!isLoadingSearch && ( )} - {activeTab !== 3 && activeTab !== 4 && ( @@ -363,43 +186,17 @@ const SearchBar = ({ autofilled }) => { )} - - {isLoadingSearch ? ( - - - - ) : ( - filteredUserData.length > 0 && ( - - ) - )} ); }; -const SearchBarContent = styled.form` - position: relative; - display: flex; - flex: 1; -`; + const Input = styled.input` box-sizing: border-box; display: flex; flex: 1; - width: 0; + width: 100%; height: 48px; padding: 13px 60px 13px 21px; margin: 10px 0px 17px 0px; diff --git a/src/components/video/IncomingCall.tsx b/src/components/video/IncomingCall.tsx index af51e51472..4d401a91cb 100644 --- a/src/components/video/IncomingCall.tsx +++ b/src/components/video/IncomingCall.tsx @@ -10,7 +10,6 @@ import * as PushAPI from '@pushprotocol/restapi' // Internal Components import { ItemHV2, SectionV2 } from 'components/reusables/SharedStylingV2'; import { VideoCallContext } from 'contexts/VideoCallContext'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { useDeviceWidthCheck } from 'hooks'; import endCallIcon from '../../assets/icons/end-call-icon.svg'; import pickCallIcon from '../../assets/icons/pick-call-icon.svg'; @@ -23,9 +22,10 @@ import VideoPlayer from './VideoPlayer'; import { device } from 'config/Globals'; import { VideoCallStatus } from '@pushprotocol/restapi'; import { appConfig } from 'config'; +import { AppContext } from 'contexts/AppContext'; const IncomingCall = () => { - const { connectedUser, createUserIfNecessary } = useContext(ChatUserContext); + const { connectedUser, createUserIfNecessary } = useContext(AppContext); const { videoCallData, acceptRequestWrapper, disconnectWrapper, setIsCallAccepted, isCallAccepted,setIncomingCallUserData,incomingCallUserData } = useContext(VideoCallContext); const [isIncomingCallMinimized, setIsIncomingCallMinimized] = useState(false); diff --git a/src/components/video/OutgoingOngoingCall.tsx b/src/components/video/OutgoingOngoingCall.tsx index 745c7cfca2..50e4892846 100644 --- a/src/components/video/OutgoingOngoingCall.tsx +++ b/src/components/video/OutgoingOngoingCall.tsx @@ -15,7 +15,7 @@ import UserInfo from 'components/video/UserInfo'; import VideoPlayer from 'components/video/VideoPlayer'; import { VideoCallContext } from 'contexts/VideoCallContext'; import { useDeviceWidthCheck } from 'hooks'; -import { BlockedLoadingI } from 'types/chat'; +import { BlockedLoadingI } from 'types/context'; import audioIcon from '../../assets/icons/audio-icon.svg'; import audioOffIcon from '../../assets/icons/audio-off-icon.svg'; import endCallIcon from '../../assets/icons/end-call-icon.svg'; @@ -25,7 +25,7 @@ import CallButton from './CallButton'; import MediaToggleButton from './MediaToggleButton'; import { VideoCallStatus } from '@pushprotocol/restapi'; import { Context } from 'modules/chat/ChatModule'; -import { AppContext } from 'types/chat'; +import { ChatUserAppContext } from 'types/chat'; import { OnConnectingVideoCall } from './OnConnectingVideoCall'; // Internal Configs @@ -69,7 +69,7 @@ const OutgoingOngoingCall = ({ blockedLoading }: OutgoingOngoingCallType) => { isCallAccepted, } = useContext(VideoCallContext); const isImmersive = useDeviceWidthCheck(425) && videoCallData.incoming[0].status === VideoCallStatus.INITIALIZED; - const { currentChat }: AppContext = useContext(Context); + const { currentChat }: ChatUserAppContext = useContext(Context); return ( diff --git a/src/components/video/VideoPlayer.tsx b/src/components/video/VideoPlayer.tsx index 5071744063..3ebef0a7cc 100644 --- a/src/components/video/VideoPlayer.tsx +++ b/src/components/video/VideoPlayer.tsx @@ -9,10 +9,9 @@ import { ImageV2, ItemHV2, ItemVV2, SpanV2 } from 'components/reusables/SharedSt import { device } from 'config/Globals'; import { VideoCallContext } from 'contexts/VideoCallContext'; import { VideoCallStatus } from '@pushprotocol/restapi'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { Context } from 'modules/chat/ChatModule'; -import { AppContext } from 'types/chat'; -import { AppContext as MainContext } from 'contexts/AppContext'; +import { ChatUserAppContext } from 'types/chat'; +import { AppContext, AppContext as MainContext } from 'contexts/AppContext'; import { AppContextType } from 'types/context'; import { shortenText } from 'helpers/UtilityHelper'; import Lock from 'assets/chat/group-chat/lockdark.svg' @@ -26,8 +25,8 @@ const VideoPlayer = ({ localVideoStyles, incoming }: VideoPlayerType) => { const localVideoRef = useRef(null); const incomingVideoRef = useRef(null); const { videoCallData, isCallAccepted } = useContext(VideoCallContext); - const { connectedUser } = useContext(ChatUserContext); - const { currentChat }: AppContext = useContext(Context); + const { connectedUser } = useContext(AppContext); + const { currentChat }: ChatUserAppContext = useContext(Context); const { web3NameList }: AppContextType = React.useContext(MainContext); const web3Name = web3NameList[videoCallData.incoming[0].address]; const theme = useTheme(); diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index 5d9107085e..a80aa2b34c 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -1,31 +1,53 @@ // React + Web3 Essentials import useModalBlur from "hooks/useModalBlur"; import React, { createContext, useContext, useEffect, useState } from "react"; -import { PushAPI } from '@pushprotocol/restapi'; +import { ProgressHookType, PushAPI } from '@pushprotocol/restapi'; // Internal Components -import { AppContextType, Web3NameListType } from "types/context" +import { AppContextType, BlockedLoadingI, ConnectedPeerIDType, LocalPeerType, Web3NameListType, onboardingProgressI } from "types/context" import { useAccount } from "hooks"; import { appConfig } from "config"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { MdError } from "react-icons/md"; import { setUserPushSDKInstance } from "redux/slices/userSlice"; -import { GlobalContext } from "./GlobalContext"; +import { GlobalContext, ReadOnlyWalletMode } from "./GlobalContext"; import useToast from "hooks/useToast"; +import { LOADER_SPINNER_TYPE } from "components/reusables/loaders/LoaderSpinner"; +import { ConnectedUser } from "types/chat"; +import * as w2wHelper from 'helpers/w2w'; + export const AppContext = createContext(null); const AppContextProvider = ({ children }) => { const { connect, provider, account, wallet, connecting } = useAccount(); - const { readOnlyWallet } = useContext(GlobalContext); const web3onboardToast = useToast(); + const { setReadOnlyWallet, readOnlyWallet, setMode } = useContext(GlobalContext); const [web3NameList, setWeb3NameList] = useState({}); - const [snapInstalled, setSnapInstalled] = useState(false); - const [SnapState, setSnapState] = useState(1); + const [pgpPvtKey, setPgpPvtKey] = useState(null); + const [connectedUser, setConnectedUser] = useState(); + const [localPeer, setLocalPeer] = useState({ + peer: '', + peerID: '' + }) + const [connectedPeerID, setConnectedPeerID] = useState({ + peerID: '' + }); + const [blockedLoading, setBlockedLoading] = useState({ + enabled: false, + title: null, + }); + const [displayQR, setDisplayQR] = useState(false); + + const { userPushSDKInstance } = useSelector((state: any) => { + return state.user; + }); + + const [SnapState, setSnapState] = useState(1); const { isModalOpen: isMetamaskPushSnapOpen, showModal: showMetamaskPushSnap, @@ -35,7 +57,7 @@ const AppContextProvider = ({ children }) => { const dispatch = useDispatch(); const handleConnectWallet = (showToast = false, toastMessage?: string) => { - if(showToast) { + if (showToast) { web3onboardToast.showMessageToast({ toastMessage: toastMessage || "Please connect your wallet to continue", toastTitle: "Connect Wallet", @@ -73,6 +95,8 @@ const AppContextProvider = ({ children }) => { observer.observe(onboardModal); } + + const initialisePushSdkGuestMode = async () => { let userInstance; userInstance = await PushAPI.initialize({ @@ -82,16 +106,137 @@ const AppContextProvider = ({ children }) => { dispatch(setUserPushSDKInstance(userInstance)); } + + + // To reformat errors + const onboardingProgressReformatter = (progressHook: ProgressHookType) => { + let onboardingProgress: onboardingProgressI = { + enabled: true, + hookInfo: progressHook, + spinnerType: LOADER_SPINNER_TYPE.PROCESSING, + progress: 0, + errorMessage:'' + }; + + if (progressHook) { + switch (progressHook.progressId) { + case "PUSH-CREATE-01": + onboardingProgress.hookInfo.progressTitle = "Creating Push Profile"; + onboardingProgress.progress = 10; + break; + case "PUSH-CREATE-02": + onboardingProgress.hookInfo.progressTitle = "1/3 - Profile Generation"; + onboardingProgress.progress = 25; + break; + case "PUSH-CREATE-03": + onboardingProgress.hookInfo.progressTitle = "2/3 - Profile Encryption"; + onboardingProgress.progress = 50; + break; + case "PUSH-CREATE-04": + onboardingProgress.hookInfo.progressTitle = "3/3 - Profile Sync"; + onboardingProgress.progress = 75; + break; + case "PUSH-CREATE-05": + onboardingProgress.hookInfo.progressTitle = "Push Profile Created"; + onboardingProgress.progress = 99; + break; + case "PUSH-DECRYPT-01": + onboardingProgress.hookInfo.progressTitle = "Decrypting Push Profile"; + break; + case "PUSH-DECRYPT-02": + onboardingProgress.enabled = false; + onboardingProgress.hookInfo.progressTitle = "Push Profile Unlocked"; + break; + // case "PUSH-UPGRADE-01": + // onboardingProgress.hookInfo.progressTitle = "1/4 - Profile Generation"; + // onboardingProgress.progress = 35; + // break; + case "PUSH-UPGRADE-02": + onboardingProgress.hookInfo.progressTitle = "1/5 - Profile Generation"; + onboardingProgress.progress = 15; + break; + case "PUSH-AUTH-UPDATE-01": + onboardingProgress.hookInfo.progressTitle = "2/5 - Decrypting Old Profile"; + onboardingProgress.progress = 30; + break; + case "PUSH-AUTH-UPDATE-02": + onboardingProgress.hookInfo.progressTitle = "3/5 - New Profile Encryption"; + onboardingProgress.progress = 45; + break; + case "PUSH-AUTH-UPDATE-03": + onboardingProgress.hookInfo.progressTitle = "4/5 - Profile Sync"; + onboardingProgress.progress = 60; + break; + case "PUSH-AUTH-UPDATE-04": + onboardingProgress.hookInfo.progressTitle = "5/5 - Upgradation Complete"; + onboardingProgress.progress = 75; + break; + // case "PUSH-UPGRADE-03": + // onboardingProgress.hookInfo.progressTitle = "3/4 - New Profile Encryption"; + // onboardingProgress.progress = 75; + // break; + // case "PUSH-UPGRADE-04": + // onboardingProgress.hookInfo.progressTitle = "4/4 - Profile Sync"; + // onboardingProgress.progress = 90; + // break; + case "PUSH-UPGRADE-05": + onboardingProgress.hookInfo.progressTitle = "Push Profile Upgraded"; + onboardingProgress.progress = 99; + break; + case "PUSH-ERROR-00": + onboardingProgress.errorMessage="User Rejected Signature"; + onboardingProgress.hookInfo.progressTitle = "User Rejected Signature"; + onboardingProgress.spinnerType = LOADER_SPINNER_TYPE.ERROR; + break; + case "PUSH-ERROR-01": + onboardingProgress.errorMessage="Upgrade Failed"; + onboardingProgress.hookInfo.progressTitle = "Upgrade Failed"; + onboardingProgress.spinnerType = LOADER_SPINNER_TYPE.ERROR; + break; + case "PUSH-ERROR-02": + onboardingProgress.errorMessage="Decrypting Keys Failed"; + onboardingProgress.hookInfo.progressTitle = "Decrypting Keys Failed"; + onboardingProgress.spinnerType = LOADER_SPINNER_TYPE.ERROR; + break; + } + } else { + + } + + // This is a new user + setBlockedLoading({ + enabled: onboardingProgress.enabled, + title: onboardingProgress.hookInfo.progressTitle, + spinnerType: onboardingProgress.spinnerType, + progressEnabled: onboardingProgress.progress ? true : false, + progress: onboardingProgress.progress, + progressNotice: onboardingProgress.hookInfo.progressInfo, + errorMessage:onboardingProgress.errorMessage, + }); + + }; + const initializePushSDK = async () => { - console.log("Initialising Push Sdk") + console.log("Initialising Push Sdk"); let userInstance; try { const librarySigner = provider?.getSigner(account); userInstance = await PushAPI.initialize(librarySigner, { env: appConfig.appEnv, // defaults to staging - account: account + account: account, + progressHook: onboardingProgressReformatter, }); + if (userInstance) { + setBlockedLoading({ + enabled: false, + title: "Push Profile Setup Complete", + spinnerType: LOADER_SPINNER_TYPE.COMPLETED, + progressEnabled: false, + progress: 100, + }); + } + dispatch(setUserPushSDKInstance(userInstance)); } catch (error) { // Handle initialization error @@ -99,6 +244,51 @@ const AppContextProvider = ({ children }) => { } }; + const getUser = async () => { + console.debug("getUser"); + const caip10: string = w2wHelper.walletToCAIP10({ account }); + const user = await userPushSDKInstance.info(); + console.log("User push sdk instance", userPushSDKInstance, user); + let connectedUser: ConnectedUser; + + // TODO: Change this to do verification on ceramic to validate if did is valid + if (user?.did.includes('did:3:')) { + throw Error('Invalid DID'); + } + + // new user might not have a private key + if (user && user.encryptedPrivateKey) { + if (user.wallets.includes(',') || !user.wallets?.toLowerCase().includes(caip10?.toLowerCase())) { + throw Error('Invalid user'); + } + const privateKeyArmored = userPushSDKInstance.decryptedPgpPvtKey; + setPgpPvtKey(privateKeyArmored); + connectedUser = { ...user, privateKey: privateKeyArmored }; + } else { + //TODO: This will not be needed now because push user is created and info has user and user.encryptedPrivateKey both + connectedUser = { + // We only need to provide this information when it's a new user + name: 'john-snow', + profilePicture: + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', + wallets: caip10, + about: '', + allowedNumMsg: 0, + did: caip10, + encryptedPrivateKey: '', + encryptionType: '', + numMsg: 0, + publicKey: '', + sigType: '', + signature: '', + linkedListHash: '', + privateKey: '', + }; + } + + setConnectedUser(connectedUser); + }; + useEffect(() => { const librarySigner = provider?.getSigner(account); if (!account || !appConfig?.appEnv) return; @@ -109,6 +299,37 @@ const AppContextProvider = ({ children }) => { } }, [account, provider, wallet]); + const createUserIfNecessary = async (): Promise => { + try { + const signer = await provider.getSigner(); + await PushAPI.user.create({ + account: account, + env: appConfig.appEnv, + signer: signer, + progressHook: onboardingProgressReformatter + }); + const createdUser = await PushAPI.user.get({ + account: account, + env: appConfig.appEnv + }); + const pvtkey = await PushAPI.chat.decryptPGPKey({ + encryptedPGPPrivateKey: createdUser.encryptedPrivateKey, + signer: signer, + env: appConfig.appEnv, + toUpgrade: true, + progressHook: onboardingProgressReformatter + }); + + const createdConnectedUser = { ...createdUser, privateKey: pvtkey }; + setConnectedUser(createdConnectedUser); + setPgpPvtKey(pvtkey); + + return createdConnectedUser; + } catch (e) { + console.error(e); + } + }; + return ( { SnapState, handleConnectWallet, setSnapInstalled, - snapInstalled + snapInstalled, + setBlockedLoading, + blockedLoading, + getUser, + connectedUser, + setConnectedUser, + pgpPvtKey, + setPgpPvtKey, + localPeer, + setLocalPeer, + connectedPeerID, + setConnectedPeerID, + displayQR, + setDisplayQR, + createUserIfNecessary }}> {children} diff --git a/src/contexts/ChatUserContext.tsx b/src/contexts/ChatUserContext.tsx deleted file mode 100644 index 47e5b6272c..0000000000 --- a/src/contexts/ChatUserContext.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import * as PushAPI from "@pushprotocol/restapi"; -import { ProgressHookType } from "@pushprotocol/restapi"; -import { LOADER_SPINNER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; -import { appConfig } from 'config'; -import { ethers } from 'ethers'; -import * as w2wHelper from 'helpers/w2w'; -import { useAccount } from "hooks"; -import React, { createContext, useState } from 'react'; -import { BlockedLoadingI, ConnectedUser, User } from 'types/chat'; - -export const ChatUserContext = createContext({}) - -//this context is global and it is called in APP.tsx -const ChatUserContextProvider = (props) => { - const [connectedUser, setConnectedUser] = useState(); - const { account, provider } = useAccount(); - - - - //this blocked loading is a modal which shows during the PGP keys generation time - const [blockedLoading, setBlockedLoading] = useState({ - enabled: false, - title: null, - }); - const [pgpPvtKey,setPgpPvtKey] = useState(null); - const [localPeer,setLocalPeer]= useState({ - peer:'', - peerID:'' - }) - const [connectedPeerID,setConnectedPeerID] = useState({ - peerID:'' - }); - const [displayQR,setDisplayQR] = useState(false); - - interface onboardingProgressI { - enabled: boolean; - hookInfo: ProgressHookType; - spinnerType: number; - progress: number; - } - - // To reformat errors - const onboardingProgressReformatter = (progressHook: ProgressHookType) => { - let onboardingProgress: onboardingProgressI = { - enabled: true, - hookInfo: progressHook, - spinnerType: LOADER_SPINNER_TYPE.PROCESSING, - progress: 0 - }; - - if (progressHook) { - switch (progressHook.progressId) { - case "PUSH-CREATE-01": - onboardingProgress.hookInfo.progressTitle = "Creating Push Profile"; - onboardingProgress.progress = 10; - break; - case "PUSH-CREATE-02": - onboardingProgress.hookInfo.progressTitle = "1/3 - Profile Generation"; - onboardingProgress.progress = 25; - break; - case "PUSH-CREATE-03": - onboardingProgress.hookInfo.progressTitle = "2/3 - Profile Encryption"; - onboardingProgress.progress = 50; - break; - case "PUSH-CREATE-04": - onboardingProgress.hookInfo.progressTitle = "3/3 - Profile Sync"; - onboardingProgress.progress = 75; - break; - case "PUSH-CREATE-05": - onboardingProgress.hookInfo.progressTitle = "Push Profile Created"; - onboardingProgress.progress = 99; - break; - case "PUSH-DECRYPT-01": - onboardingProgress.hookInfo.progressTitle = "Decrypting Push Profile"; - break; - case "PUSH-DECRYPT-02": - onboardingProgress.enabled = false; - onboardingProgress.hookInfo.progressTitle = "Push Profile Unlocked"; - break; - case "PUSH-UPGRADE-01": - onboardingProgress.hookInfo.progressTitle = "1/4 - Profile Generation"; - onboardingProgress.progress = 35; - break; - case "PUSH-UPGRADE-02": - onboardingProgress.hookInfo.progressTitle = "2/4 - Decrypting Old Profile"; - onboardingProgress.progress = 50; - break; - case "PUSH-UPGRADE-03": - onboardingProgress.hookInfo.progressTitle = "3/4 - New Profile Encryption"; - onboardingProgress.progress = 75; - break; - case "PUSH-UPGRADE-04": - onboardingProgress.hookInfo.progressTitle = "4/4 - Profile Sync"; - onboardingProgress.progress = 90; - break; - case "PUSH-UPGRADE-05": - onboardingProgress.hookInfo.progressTitle = "Push Profile Upgraded"; - onboardingProgress.progress = 99; - break; - case "PUSH-ERROR-00": - onboardingProgress.hookInfo.progressTitle = "User Rejected Signature"; - onboardingProgress.spinnerType = LOADER_SPINNER_TYPE.ERROR; - break; - case "PUSH-ERROR-01": - onboardingProgress.hookInfo.progressTitle = "Upgrade Failed"; - onboardingProgress.spinnerType = LOADER_SPINNER_TYPE.ERROR; - break; - case "PUSH-ERROR-02": - onboardingProgress.hookInfo.progressTitle = "Decrypting Keys Failed"; - onboardingProgress.spinnerType = LOADER_SPINNER_TYPE.ERROR; - break; - } - } else { - - } - - // This is a new user - setBlockedLoading({ - enabled: onboardingProgress.enabled, - title: onboardingProgress.hookInfo.progressTitle, - spinnerType: onboardingProgress.spinnerType, - progressEnabled: onboardingProgress.progress ? true : false, - progress: onboardingProgress.progress, - progressNotice: onboardingProgress.hookInfo.progressInfo, - }); - - }; - - const getUser = async () => { - console.debug("getUser"); - const caip10: string = w2wHelper.walletToCAIP10({ account }); - const user: User = await PushAPI.user.get({ - account: caip10, - env: appConfig.appEnv - }); - let connectedUser: ConnectedUser; - - // TODO: Change this to do verification on ceramic to validate if did is valid - if (user?.did.includes('did:3:')) { - throw Error('Invalid DID'); - } - - // new user might not have a private key - if (user && user.encryptedPrivateKey) { - if (user.wallets.includes(',') || !user.wallets?.toLowerCase().includes(caip10?.toLowerCase())) { - throw Error('Invalid user'); - } - const _signer = await provider.getSigner(); - const privateKeyArmored = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: user.encryptedPrivateKey, - signer: _signer, - env: appConfig.appEnv, - toUpgrade: true, - progressHook: onboardingProgressReformatter - }); - - setPgpPvtKey(privateKeyArmored); - connectedUser = { ...user, privateKey: privateKeyArmored }; - } else { - connectedUser = { - // We only need to provide this information when it's a new user - name: 'john-snow', - profilePicture: - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAvklEQVR4AcXBsW2FMBiF0Y8r3GQb6jeBxRauYRpo4yGQkMd4A7kg7Z/GUfSKe8703fKDkTATZsJsrr0RlZSJ9r4RLayMvLmJjnQS1d6IhJkwE2bT13U/DBzp5BN73xgRZsJMmM1HOolqb/yWiWpvjJSUiRZWopIykTATZsJs5g+1N6KSMiO1N/5DmAkzYTa9Lh6MhJkwE2ZzSZlo7xvRwson3txERzqJhJkwE2bT6+JhoKTMJ2pvjAgzYSbMfgDlXixqjH6gRgAAAABJRU5ErkJggg==', - wallets: caip10, - about: '', - allowedNumMsg: 0, - did: caip10, - encryptedPrivateKey: '', - encryptionType: '', - numMsg: 0, - publicKey: '', - sigType: '', - signature: '', - linkedListHash: '', - privateKey: '', - }; - } - - setConnectedUser(connectedUser); - }; - - const createUserIfNecessary = async (): Promise => { - try { - const signer = await provider.getSigner(); - await PushAPI.user.create({ - account: account, - env: appConfig.appEnv, - signer: signer, - progressHook: onboardingProgressReformatter - }); - const createdUser = await PushAPI.user.get({ - account: account, - env: appConfig.appEnv - }); - const pvtkey = await PushAPI.chat.decryptPGPKey({ - encryptedPGPPrivateKey: createdUser.encryptedPrivateKey, - signer: signer, - env: appConfig.appEnv, - toUpgrade: true, - progressHook: onboardingProgressReformatter - }); - - const createdConnectedUser = { ...createdUser, privateKey: pvtkey }; - setConnectedUser(createdConnectedUser); - setPgpPvtKey(pvtkey); - - return createdConnectedUser ; - } catch (e) { - console.error(e); - } - }; - - return ( - - {props.children} - - ); -}; - -export default ChatUserContextProvider; diff --git a/src/contexts/VideoCallContext.tsx b/src/contexts/VideoCallContext.tsx index 69955fe840..70f9234420 100644 --- a/src/contexts/VideoCallContext.tsx +++ b/src/contexts/VideoCallContext.tsx @@ -7,9 +7,9 @@ import { VideoCallStatus } from '@pushprotocol/restapi'; import { appConfig } from 'config'; import { initVideoCallData } from '@pushprotocol/restapi/src/lib/video'; -import { ChatUserContext } from './ChatUserContext'; import { User } from 'types/chat'; import { useAccount } from 'hooks'; +import { AppContext } from './AppContext'; interface RequestWrapperOptionsType { senderAddress: string; @@ -40,7 +40,7 @@ const VideoCallContextProvider: React.FC = ({ children }) => { const [isCallAccepted, setIsCallAccepted] = useState(false); const [incomingCallUserData, setIncomingCallUserData] = useState(null); const { chainId, account, provider } = useAccount(); - const { connectedUser, createUserIfNecessary } = useContext(ChatUserContext); + const { connectedUser, createUserIfNecessary} = useContext(AppContext); const [data, setData] = useState(initVideoCallData); diff --git a/src/hooks/usePeer.ts b/src/hooks/usePeer.ts index cc77f254de..34eeef45b1 100644 --- a/src/hooks/usePeer.ts +++ b/src/hooks/usePeer.ts @@ -1,56 +1,55 @@ -import React, { useContext, useEffect, useState } from "react"; -import { Peer } from "peerjs"; -import { ChatUserContext } from "contexts/ChatUserContext"; +import React, { useContext, useEffect, useState } from 'react'; +import { Peer } from 'peerjs'; +import { AppContext } from 'contexts/AppContext'; const usePeer = () => { - const { setLocalPeer,localPeer,setConnectedPeerID } = useContext(ChatUserContext); - const [myPeer, setPeer] = useState(localPeer.peer); - const [myPeerID, setMyPeerID] = useState(localPeer.peerID); - - - const cleanUp = () => { - if (myPeer) { - myPeer.disconnect(); - myPeer.destroy(); - } - setPeer(null); - setMyPeerID(null); - setLocalPeer({peer:'',peerID:''}) - setConnectedPeerID({peerID:''}) + const { setLocalPeer, localPeer, setConnectedPeerID } = useContext(AppContext); + const [myPeer, setPeer] = useState(localPeer.peer); + const [myPeerID, setMyPeerID] = useState(localPeer.peerID); + + const cleanUp = () => { + if (myPeer) { + myPeer.disconnect(); + myPeer.destroy(); } - - useEffect(() => { - const peer = myPeer ? myPeer : new Peer(); - - peer.on('open', () => { - setPeer(peer); - setMyPeerID(peer.id); - setLocalPeer({ - peer:peer, - peerID:peer.id - }) - }) - - peer.on("connection", (connection) => { - connection.on("data", (data) => { - setConnectedPeerID({peerID:data.peerID}) - }); + setPeer(null); + setMyPeerID(null); + setLocalPeer({ peer: '', peerID: '' }); + setConnectedPeerID({ peerID: '' }); + }; + + useEffect(() => { + const peer = myPeer ? myPeer : new Peer(); + + peer.on('open', () => { + setPeer(peer); + setMyPeerID(peer.id); + setLocalPeer({ + peer: peer, + peerID: peer.id, }); + }); - peer.on('disconnected', () => { - cleanUp() + peer.on('connection', (connection) => { + connection.on('data', (data) => { + setConnectedPeerID({ peerID: data.peerID }); }); + }); - peer.on('close', () => { - cleanUp() - }); + peer.on('disconnected', () => { + cleanUp(); + }); - peer.on('error', (error) => { - cleanUp() - }); - }, []) + peer.on('close', () => { + cleanUp(); + }); + + peer.on('error', (error) => { + cleanUp(); + }); + }, []); - return [myPeer, myPeerID]; -} + return [myPeer, myPeerID]; +}; -export default usePeer; \ No newline at end of file +export default usePeer; diff --git a/src/index.js b/src/index.js index d04380089a..b825d09745 100644 --- a/src/index.js +++ b/src/index.js @@ -11,7 +11,6 @@ import { BrowserRouter } from "react-router-dom"; // Internal Components import App from "./App"; -import ChatUserContextProvider from './contexts/ChatUserContext'; import ErrorContextProvider from './contexts/ErrorContext'; import { VideoCallContextProvider } from './contexts/VideoCallContext'; import "./index.css"; @@ -22,6 +21,7 @@ import GlobalContextProvider from './contexts/GlobalContext'; // Internal Configs import * as dotenv from "dotenv"; import { web3Onboard } from './connectors/web3Onboard'; +import AppContextProvider from './contexts/AppContext'; // enable environmental variables across the entire application dotenv.config(); @@ -52,13 +52,13 @@ ReactDOM.render( - - + + - - + + diff --git a/src/modules/chat/ChatModule.tsx b/src/modules/chat/ChatModule.tsx index 72aa43742c..867b9c3c6c 100644 --- a/src/modules/chat/ChatModule.tsx +++ b/src/modules/chat/ChatModule.tsx @@ -1,10 +1,10 @@ // React + Web3 Essentials import { ethers } from 'ethers'; import React, { useContext, useEffect, useState } from 'react'; -import { useNavigate } from "react-router-dom"; +import { useNavigate } from 'react-router-dom'; // External Packages -import * as PushAPI from "@pushprotocol/restapi"; +import * as PushAPI from '@pushprotocol/restapi'; import ReactGA from 'react-ga'; import { QueryClient, QueryClientProvider } from 'react-query'; import { ReactQueryDevtools } from 'react-query/devtools'; @@ -12,38 +12,38 @@ import { ToastOptions } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import { useClickAway } from 'react-use'; import styled, { useTheme } from 'styled-components'; +import { useSelector } from 'react-redux'; // Internal Compoonents +import { AppContext } from 'contexts/AppContext'; import ChatQR from 'components/chat/w2wChat/chatQR/chatQR'; import MobileView from 'components/chat/w2wChat/chatQR/mobileView'; import { CreateGroupModalContent } from 'components/chat/w2wChat/groupChat/createGroup/CreateGroupModalContent'; import { GroupInfoModalContent } from 'components/chat/w2wChat/groupChat/groupInfo/groupInfoModalContent'; +import { ItemHV2, ItemVV2 } from 'components/reusables/SharedStylingV2'; import LoaderSpinner, { LOADER_OVERLAY, LOADER_SPINNER_TYPE, LOADER_TYPE, - PROGRESS_POSITIONING + PROGRESS_POSITIONING, } from 'components/reusables/loaders/LoaderSpinner'; -import { ItemHV2, ItemVV2 } from 'components/reusables/SharedStylingV2'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { VideoCallContext } from 'contexts/VideoCallContext'; import { caip10ToWallet } from 'helpers/w2w'; import * as w2wHelper from 'helpers/w2w/'; import { checkIfGroup, rearrangeMembers } from 'helpers/w2w/groupChat'; -import { useAccount,useDeviceWidthCheck, useSDKSocket } from 'hooks'; +import { useAccount, useDeviceWidthCheck, useSDKSocket } from 'hooks'; import useModalBlur, { MODAL_POSITION } from 'hooks/useModalBlur'; import useToast from 'hooks/useToast'; import ChatBoxSection from 'sections/chat/ChatBoxSection'; import ChatSidebarSection from 'sections/chat/ChatSidebarSection'; import VideoCallSection from 'sections/video/VideoCallSection'; -import { AppContext, Feeds, MessageIPFS, MessageIPFSWithCID, User, VideoCallInfoI } from 'types/chat'; +import { ChatUserAppContext, Feeds, MessageIPFS, MessageIPFSWithCID, User, VideoCallInfoI } from 'types/chat'; import { checkIfIntent, getUpdatedChatAndIntent, getUpdatedGroupInfo } from 'helpers/w2w/user'; // Internal Configs +import { ChatUIProvider, darkChatTheme } from '@pushprotocol/uiweb'; import { appConfig } from 'config'; import GLOBALS, { device, globalsMargin } from 'config/Globals'; -import { fetchIntent } from 'helpers/w2w/user'; -import { ChatUIProvider, darkChatTheme } from '@pushprotocol/uiweb'; export const ToastPosition: ToastOptions = { position: 'top-right', @@ -55,19 +55,34 @@ export const ToastPosition: ToastOptions = { progress: 0, }; -export const Context = React.createContext(null); +export const Context = React.createContext(null); // Create Header function Chat({ chatid }) { const { account, chainId, provider } = useAccount(); - const { getUser, pgpPvtKey,connectedUser, setConnectedUser, blockedLoading, setBlockedLoading, displayQR, setDisplayQR } = - useContext(ChatUserContext); - const { videoCallData } = useContext(VideoCallContext); + const { videoCallData } = useContext(VideoCallContext); + + const { + blockedLoading, + setBlockedLoading, + getUser, + pgpPvtKey, + connectedUser, + setConnectedUser, + displayQR, + setDisplayQR + } = useContext(AppContext); + + const { userPushSDKInstance } = useSelector((state: any) => { + return state.user; + }); const theme = useTheme(); const [viewChatBox, setViewChatBox] = useState(false); const [currentChat, setCurrentChat] = useState(); + const [selectedChatId, setSelectedChatId] = useState(); + const [receivedIntents, setReceivedIntents] = useState([]); const [isLoading, setIsLoading] = useState(true); const [loadingMessage, setLoadingMessage] = useState(''); @@ -84,93 +99,107 @@ function Chat({ chatid }) { const containerRef = React.useRef(null); - const socketData = useSDKSocket({ account, chainId, env: appConfig.appEnv,socketType: 'chat' }); + const socketData = useSDKSocket({ account, chainId, env: appConfig.appEnv, socketType: 'chat' }); - useEffect(()=>{ - if(connectedUser && socketData.messagesSinceLastConnection && ((w2wHelper.caip10ToWallet(socketData.messagesSinceLastConnection.fromCAIP10)).toLowerCase() !== account.toLowerCase())){ - if(currentChat) - getUpdatedInbox(socketData.messagesSinceLastConnection) + useEffect(() => { + if ( + connectedUser && + socketData.messagesSinceLastConnection && + w2wHelper.caip10ToWallet(socketData.messagesSinceLastConnection.fromCAIP10).toLowerCase() !== + account.toLowerCase() + ) { + if (currentChat) getUpdatedInbox(socketData.messagesSinceLastConnection); } - },[socketData.messagesSinceLastConnection]) + }, [socketData.messagesSinceLastConnection]); - useEffect(()=>{ - if(connectedUser && socketData.groupInformationSinceLastConnection) { + useEffect(() => { + if (connectedUser && socketData.groupInformationSinceLastConnection) { getUpdatedGroup(socketData.groupInformationSinceLastConnection); } - },[socketData.groupInformationSinceLastConnection]) - - - - const getUpdatedInbox = async(message) => { - let isListUpdated=false; - const {updatedInbox,isInboxUpdated}=await getUpdatedChatAndIntent({chatList:inbox,message,connectedUser,account,checkInbox:true}); - if(isInboxUpdated){ - isListUpdated=true; + }, [socketData.groupInformationSinceLastConnection]); + + const getUpdatedInbox = async (message) => { + let isListUpdated = false; + const { updatedInbox, isInboxUpdated } = await getUpdatedChatAndIntent({ + chatList: inbox, + message, + connectedUser, + account, + checkInbox: true, + }); + if (isInboxUpdated) { + isListUpdated = true; setInbox(updatedInbox); - } - else{ - const {updatedIntents,isIntentsUpdated}=await getUpdatedChatAndIntent({chatList:receivedIntents,message,connectedUser,account,checkInbox:false}); - if(isIntentsUpdated){ - isListUpdated=true; + } else { + const { updatedIntents, isIntentsUpdated } = await getUpdatedChatAndIntent({ + chatList: receivedIntents, + message, + connectedUser, + account, + checkInbox: false, + }); + if (isIntentsUpdated) { + isListUpdated = true; setReceivedIntents(updatedIntents); } } - if(!isListUpdated){ + if (!isListUpdated) { const fetchedChat = await PushAPI.chat.chat({ account: account, toDecrypt: true, pgpPrivateKey: connectedUser?.privateKey, recipient: caip10ToWallet(message?.fromCAIP10), - env: appConfig.appEnv + env: appConfig.appEnv, }); - if(checkIfIntent({chat:fetchedChat, account})){ - setReceivedIntents(prev=> [fetchedChat , ...prev]); - - } - else{ - setInbox(prev=>[fetchedChat,...prev]) + if (checkIfIntent({ chat: fetchedChat, account })) { + setReceivedIntents((prev) => [fetchedChat, ...prev]); + } else { + setInbox((prev) => [fetchedChat, ...prev]); } - } - - } + }; -const getUpdatedGroup = async(groupInfo) => { - let isGroupUpdated=false; - const {updatedInbox, isInboxUpdated} = await getUpdatedGroupInfo({chatList:inbox, groupInfo, checkInbox:true}); - if(isInboxUpdated){ - setInbox(updatedInbox); - isGroupUpdated=true; - } - else{ - const {updatedIntents, isIntentsUpdated} = await getUpdatedGroupInfo({chatList:intents, groupInfo,checkInbox:false}) - if(isIntentsUpdated){ - setReceivedIntents(updatedIntents); - isGroupUpdated=true; - } - } - if(!isGroupUpdated){ - const fetchedChat = await PushAPI.chat.chat({ - account: account, - toDecrypt: true, - pgpPrivateKey: connectedUser?.privateKey, - recipient: groupInfo?.chatId, - env: appConfig.appEnv + const getUpdatedGroup = async (groupInfo) => { + let isGroupUpdated = false; + const { updatedInbox, isInboxUpdated } = await getUpdatedGroupInfo({ + chatList: inbox, + groupInfo, + checkInbox: true, }); - if(checkIfIntent({chat:fetchedChat, account})){ - setReceivedIntents(prev=> [fetchedChat, ...prev]); + if (isInboxUpdated) { + setInbox(updatedInbox); + isGroupUpdated = true; + } else { + const { updatedIntents, isIntentsUpdated } = await getUpdatedGroupInfo({ + chatList: intents, + groupInfo, + checkInbox: false, + }); + if (isIntentsUpdated) { + setReceivedIntents(updatedIntents); + isGroupUpdated = true; + } } - else{ - setInbox(prev=>[fetchedChat,...prev]) - } - } - - } + if (!isGroupUpdated) { + const fetchedChat = await PushAPI.chat.chat({ + account: account, + toDecrypt: true, + pgpPrivateKey: connectedUser?.privateKey, + recipient: groupInfo?.chatId, + env: appConfig.appEnv, + }); + if (checkIfIntent({ chat: fetchedChat, account })) { + setReceivedIntents((prev) => [fetchedChat, ...prev]); + } else { + setInbox((prev) => [fetchedChat, ...prev]); + } + } + }; // React GA Analytics ReactGA.pageview('/chat'); - useEffect(()=>{ + useEffect(() => { setChat(null); setInbox([]); setReceivedIntents([]); @@ -178,7 +207,7 @@ const getUpdatedGroup = async(groupInfo) => { setViewChatBox(false); setIsLoading(true); setConnectedUser(null); - },[account]) + }, [account]); // Rest of the loading logic useEffect(() => { @@ -186,17 +215,17 @@ const getUpdatedGroup = async(groupInfo) => { setConnectedUser(connectedUser); connectUser(); } - }, [connectedUser]); + }, [connectedUser, userPushSDKInstance]); - useEffect(()=>{ - if(currentChat?.threadhash==null){ - for(let i=0;i { + if (currentChat?.threadhash == null) { + for (let i = 0; i < inbox?.length; i++) { + if (inbox[i]?.wallets === currentChat?.wallets) { setChat(inbox[i]); } } } - },[inbox]) + }, [inbox]); const closeQRModal = () => { setDisplayQR(false); @@ -218,22 +247,19 @@ const getUpdatedGroup = async(groupInfo) => { showModal: showCreateGroupModal, ModalComponent: CreateGroupModalComponent, } = useModalBlur(); - // const { pgpPvtKey } = useContext(ChatUserContext); - const connectUser = async (): Promise => { - const caip10:string = w2wHelper.walletToCAIP10({account}); + const caip10: string = w2wHelper.walletToCAIP10({ account }); const signer = await provider.getSigner(); setSignerData(signer); - - if(connectedUser?.wallets?.toLowerCase() !== caip10?.toLowerCase()){ + + if (connectedUser?.wallets?.toLowerCase() !== caip10?.toLowerCase()) { await getUser(); } - setBlockedLoading({ enabled: false, - title: "Push Profile Setup Complete", + title: 'Push Profile Setup Complete', spinnerType: LOADER_SPINNER_TYPE.COMPLETED, progressEnabled: false, progress: 100, @@ -245,7 +271,7 @@ const getUpdatedGroup = async(groupInfo) => { // reformat chatid first chatid = reformatChatId(chatid); - if(connectedUser?.wallets?.toLowerCase() === caip10?.toLowerCase()){ + if (connectedUser?.wallets?.toLowerCase() === caip10?.toLowerCase()) { // dynamic url setCurrentTab(4); } @@ -283,6 +309,10 @@ const getUpdatedGroup = async(groupInfo) => { return chatid; } + // check if .wallet is at the end, then skip anything else + if (chatid.endsWith('.wallet')) { + return chatid; + } // check if this is eip155: which is considered default and therefore remove it if (chatid.startsWith('eip155:') && !chatid.includes(':nft')) { chatid = chatid.replace('eip155:', ''); @@ -312,160 +342,182 @@ const getUpdatedGroup = async(groupInfo) => { } return chatid; - } + }; let navigate = useNavigate(); const setChat = (feed: Feeds): void => { if (feed) { setViewChatBox(true); - if(checkIfGroup(feed)) - { - rearrangeMembers(feed,connectedUser); + if (checkIfGroup(feed)) { + rearrangeMembers(feed, connectedUser); } // check and set to wallet or chat id let chatid = feed.did; - console.log("chatiddd",chatid); if (!chatid) { // check group information if (feed.groupInformation) { chatid = feed.groupInformation.chatId; } } - chatid = reformatChatId(chatid); - setCurrentChat(feed); + // chatid = reformatChatId(chatid); + // setCurrentChat(feed); // lastly, set navigation for dynamic linking - navigate(`/chat/${chatid}`); + // navigate(`/chat/${chatid}`); } else { setViewChatBox(false); - navigate(`/chat`); + // navigate(`/chat`); } }; useEffect(() => { - }, [account, connectedUser?.privateKey]) + let formattedchatId = selectedChatId || chatid; + + if (formattedchatId) { + setViewChatBox(true); + formattedchatId = reformatChatId(formattedchatId); + navigate(`/chat/${formattedchatId}`); + } + else + { + setViewChatBox(false); + navigate(`/chat`); + } + }, [selectedChatId]); + useEffect(() => {}, [account, connectedUser?.privateKey]); return ( - - - {!isLoading ? ( - - - - - - + + {!isLoading ? ( + + - - - {}} - toastObject={groupInfoToast} - modalPadding="0px" - modalPosition={MODAL_POSITION.ON_PARENT} - /> - - - {/* Video Call Section */} - {videoCallData.incoming[0].status > 0 && ( - - )} - - {displayQR && !isMobile && ( - <> - + + + + + + {}} + toastObject={groupInfoToast} + modalPadding="0px" + modalPosition={MODAL_POSITION.ON_PARENT} + /> + - {/* */} - - )} + {/* Video Call Section */} + {videoCallData.incoming[0].status > 0 && } + + {displayQR && !isMobile && ( + <> + - {displayQR && isMobile && ( - <> - - - )} - - {/* The rest of your application */} - - - ) : ( - - )} - - {/* This always needs to be last */} - {blockedLoading.enabled && ( - - )} - + /> */} + + )} + + {displayQR && isMobile && ( + <> + + + )} + + {/* The rest of your application */} + + + ) : ( + + )} + + {/* This always needs to be last */} + {blockedLoading.enabled && ( + + )} + ); @@ -488,22 +540,21 @@ const Container = styled.div` box-sizing: border-box; margin: ${GLOBALS.ADJUSTMENTS.MARGIN.MINI_MODULES.DESKTOP}; - height: calc(100vh - ${GLOBALS.CONSTANTS.HEADER_HEIGHT}px - ${globalsMargin.MINI_MODULES.DESKTOP.TOP} - ${ - globalsMargin.MINI_MODULES.DESKTOP.BOTTOM -}); + height: calc(100vh - ${GLOBALS.CONSTANTS.HEADER_HEIGHT}px - ${globalsMargin.MINI_MODULES.DESKTOP.TOP} - ${globalsMargin.MINI_MODULES.DESKTOP.BOTTOM + }); @media ${device.laptop} { margin: ${GLOBALS.ADJUSTMENTS.MARGIN.MINI_MODULES.TABLET}; height: calc(100vh - ${GLOBALS.CONSTANTS.HEADER_HEIGHT}px - ${globalsMargin.MINI_MODULES.TABLET.TOP} - ${ - globalsMargin.MINI_MODULES.TABLET.BOTTOM - }); + globalsMargin.MINI_MODULES.TABLET.BOTTOM +}); } @media ${device.mobileL} { margin: ${GLOBALS.ADJUSTMENTS.MARGIN.MINI_MODULES.MOBILE}; height: calc(100vh - ${GLOBALS.CONSTANTS.HEADER_HEIGHT}px - ${globalsMargin.MINI_MODULES.MOBILE.TOP} - ${ - globalsMargin.MINI_MODULES.MOBILE.BOTTOM - }); + globalsMargin.MINI_MODULES.MOBILE.BOTTOM +}); border: ${GLOBALS.ADJUSTMENTS.RADIUS.LARGE}; `; diff --git a/src/modules/space/SpaceModule.tsx b/src/modules/space/SpaceModule.tsx index 389bf3905a..844f482d8a 100644 --- a/src/modules/space/SpaceModule.tsx +++ b/src/modules/space/SpaceModule.tsx @@ -12,7 +12,6 @@ import styled from 'styled-components'; import GLOBALS, { device, globalsMargin } from '../../config/Globals'; import * as w2wHelper from 'helpers/w2w/'; // import { SpaceGlobalContext, SpaceLocalContext, SpaceLocalContextProvider } from 'contexts'; -// import { ChatUserContext } from 'contexts/ChatUserContext'; // import { getSpaceRequests, getSpaces } from 'services/space'; // import { getSpaceRequestsFromIndexedDB, getSpacesFromIndexedDB } from 'helpers/space'; // import { SpaceInfoModalContent } from 'components/space/spaceModals/spaceInfoModal'; @@ -24,7 +23,6 @@ import * as w2wHelper from 'helpers/w2w/'; // import { useDeviceWidthCheck } from 'hooks/useDeviceWidthCheck'; import SpaceFeedSection from 'sections/space/SpaceFeedSection'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { appConfig } from 'config'; import * as PushAPI from '@pushprotocol/restapi'; import { ConnectedUser, User } from 'types/chat'; @@ -34,14 +32,16 @@ import { Item } from 'primaries/SharedStyling'; import { ItemVV2 } from 'components/reusables/SharedStylingV2'; import { useAccount, useSDKSocket } from 'hooks'; import { SpaceContext } from 'contexts/SpaceContext'; +import { AppContext } from 'contexts/AppContext'; export const SpaceModule = ({ spaceid }) => { const { account, chainId } = useAccount(); - const { pgpPvtKey, getUser, setPgpPvtKey, connectedUser, setConnectedUser, createUserIfNecessary } = useContext(ChatUserContext); const [isLoading, setIsLoading] = useState(true); - useSDKSocket({ account, chainId, env: appConfig.appEnv}); + const { getUser, connectedUser, setConnectedUser, pgpPvtKey, setPgpPvtKey, createUserIfNecessary } = useContext(AppContext); + + useSDKSocket({ account, chainId, env: appConfig.appEnv }); useEffect(() => { setIsLoading(true); @@ -70,13 +70,13 @@ export const SpaceModule = ({ spaceid }) => { return ( - {isLoading ? + {isLoading ? - - - - - : } + + + + + : } ); }; diff --git a/src/primaries/Profile.tsx b/src/primaries/Profile.tsx index b380c19b76..91394683b8 100644 --- a/src/primaries/Profile.tsx +++ b/src/primaries/Profile.tsx @@ -1,8 +1,9 @@ // React + Web3 Essentials -import React, { useContext, useRef } from 'react'; +import React, { useContext, useEffect, useRef } from 'react'; // External Packages import styled, { useTheme } from 'styled-components'; +import { useSelector } from 'react-redux'; // Internal Compoonents import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; @@ -19,19 +20,23 @@ import APP_PATHS from 'config/AppPaths'; import { AppContext } from 'contexts/AppContext'; import { ErrorContext } from 'contexts/ErrorContext'; import { AppContextType } from 'types/context'; -import { GlobalContext, GlobalContextType } from 'contexts/GlobalContext'; +import { GlobalContext, GlobalContextType, ReadOnlyWalletMode } from 'contexts/GlobalContext'; import { SpanV2 } from 'components/reusables/SharedStylingV2.js'; // Create Header const Profile = ({ isDarkMode }) => { const { web3NameList }: AppContextType = useContext(AppContext); - const { setReadOnlyWallet, readOnlyWallet, mode }: GlobalContextType = useContext(GlobalContext); + const { setReadOnlyWallet, readOnlyWallet, mode,setMode }: GlobalContextType = useContext(GlobalContext); const { authError } = useContext(ErrorContext); const toggleArrowRef = useRef(null); const dropdownRef = useRef(null); const modalRef = React.useRef(null); const { account, disconnect, wallet } = useAccount(); + const { userPushSDKInstance } = useSelector((state: any) => { + return state.user; + }); + // resolve web3 name useResolveWeb3Name(account); const web3Name = web3NameList[account] @@ -107,7 +112,7 @@ const Profile = ({ isDarkMode }) => { ) : ( <>{shortenText(account, 5)} )} - {mode} + {mode ? mode : userPushSDKInstance?.readMode && ReadOnlyWalletMode.READ_ONLY_MODE } arrow { // theme context const theme = useTheme(); - const { receivedIntents, setReceivedIntents, filteredUserData } = useContext(Context); + const { setSelectedChatId } = useContext(Context); - const isNewTagVisible = getIsNewTagVisible(new Date("2023-02-22T00:00:00.000"), 90); + const isNewTagVisible = getIsNewTagVisible(new Date('2023-02-22T00:00:00.000'), 90); - const { connectedUser, displayQR, setDisplayQR } = useContext(ChatUserContext); + const { connectedUser, displayQR, setDisplayQR, initializePushSDK } = useContext(AppContext); + const [searchedUser, setSearchedUser] = useState(''); const { activeTab, setActiveTab } = useContext(Context); - const [updateProfileImage, setUserProfileImage] = useState(connectedUser?.profilePicture); + const [requestChatList, setRequestChatList] = useState([]); + const [requestLoadingData, setRequestLoadingData] = useState(); const [loadingRequests, setLoadingRequests] = useState(true); const [showQR, setShowQR] = useState(false); const containerRef = React.useRef(null); - const updateProfile = (image: string) => { - setUserProfileImage(image); - }; - - const getRequests = async (): Promise => { - await fetchIntentApi(); - setLoadingRequests(false) - }; - useEffect(() => { - // This will run when the page first loads - getRequests(); - }, []); + const { userPushSDKInstance } = useSelector((state: any) => { + return state.user; + }); const closeQRDropdown = () => { setShowQR(false); + }; + useClickAway(containerRef, () => closeQRDropdown()); + + const formatChatParticipant = async (chatParticipant: string, chatId: string) => { + let formattedChatParticipant = chatParticipant; + + //Checking if the user has signed the message or not + if (userPushSDKInstance.decryptedPgpPvtKey) { + if (!formattedChatParticipant.includes('.')) { + if (!await ethers.utils.isAddress(caip10ToWallet(formattedChatParticipant))) + formattedChatParticipant = chatId; + } + return formattedChatParticipant; + } else { + await initializePushSDK(); + return null; + } } - useClickAway(containerRef, () => closeQRDropdown()) - const fetchIntentApi = async (): Promise => { - const intents = await fetchIntent({connectedUser}); - if (JSON.stringify(intents) != JSON.stringify(receivedIntents)) { - setReceivedIntents(intents); - setLoadingRequests(false); + const handleCreateGroup = async () => { + if (userPushSDKInstance.decryptedPgpPvtKey) { + showCreateGroupModal(); + } else { + await initializePushSDK(); } - setLoadingRequests(false); - return intents; - }; - + } // RENDER return ( - + {/* Header */} - {activeTab == 0 || activeTab == 1 ? ( + {activeTab !== 3 && activeTab !== 4 && ( - + {/* Set active and onCLick to customize tab */} { > Requests - {!loadingRequests && receivedIntents.length > 0 && ( - - {receivedIntents.length} - + {(requestLoadingData && requestLoadingData?.loading) && ( + )} + + {(requestLoadingData && !requestLoadingData?.loading) && + requestChatList.length > 0 && ( + + {requestChatList.length} + + )} - ) : null} + )} {/* Main Content */} { alignItems="stretch" // ref={containerRef} onClick={closeQRDropdown} + width="100%" > - {activeTab == 0 && } - {activeTab == 0 && filteredUserData.length == 0 && ( + {activeTab == 0 && ( + + )} + {activeTab == 0 && ( showCreateGroupModal()} + onClick={handleCreateGroup} background="transparent" hover={theme.chat.snapFocusBg} hoverBackground="transparent" - onMouseEnter={() => - StyleHelper.changeStyle(createGroupOnMouseEnter) - } - onMouseLeave={() => - StyleHelper.changeStyle(createGroupOnMouseLeave) - } + onMouseEnter={() => StyleHelper.changeStyle(createGroupOnMouseEnter)} + onMouseLeave={() => StyleHelper.changeStyle(createGroupOnMouseLeave)} > @@ -220,26 +244,84 @@ const ChatSidebarSection = ({ showCreateGroupModal, autofilledSearch }) => { )} - {activeTab == 0 && filteredUserData.length == 0 && ( - + setSelectedChatId(await formatChatParticipant(chatParticipant, chatid))} + + onUnreadCountChange={(count) => { + // console.log('Count is: ', count); + }} + /> + + + {/* Set Requests */} + + { console.log(chatParticipant); setSelectedChatId(await formatChatParticipant(chatParticipant, chatid)) }} + onUnreadCountChange={(count) => { + // console.log('Count is: ', count); + }} + onLoading={(loadingData) => setRequestLoadingData(loadingData)} + onPaging={(chats) => setRequestChatList(chats)} + onPreload={(chats) => setRequestChatList(chats)} + /> + + {activeTab == 3 && ( + + )} + {activeTab == 4 && ( + )} - {activeTab == 1 && ( - <> - - + {/* Set Search */} + {searchedUser && (activeTab === 3 || activeTab === 4) && ( + + setSelectedChatId(await formatChatParticipant(chatParticipant, chatid))} + onUnreadCountChange={(count) => { + // console.log('Count is: ', count); + }} + /> + )} - {activeTab == 3 && } - {activeTab == 4 && } + + {/* Footer */} - {showQR ? ( setDisplayQR(!displayQR)} @@ -251,16 +333,17 @@ const ChatSidebarSection = ({ showCreateGroupModal, autofilledSearch }) => { }} > - Link Mobile App + Link Mobile App ) : null} - - + {/* + /> */} + ); @@ -273,58 +356,56 @@ const TabButton = styled(ButtonV2)` `; const ProfileContainer = styled(ItemHV2)` - flex: initial; - justify-content: space-between; - margin: 15px 0px 5px 0px; - padding: 14px 10px 0px 10px; - border-top: ${props => props.borderTop}; + flex: initial; + justify-content: space-between; + // padding: 14px 10px 0px 10px; + border-top: ${(props) => props.borderTop}; `; const QRCodeContainer = styled.div` -display: flex; -flex-direction: row; -align-items: center; -padding: 8px; -gap: 9px; -width: 200px; -z-index:100; -height: 48px; -background: #FFFFFF; -border: 1px solid #BAC4D6; -box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.05); -border-radius: 12px; -cursor:pointer; -position: absolute; -z-index: 100; -bottom: 45px; - -@media (max-width:768px){ -right:30px; -} - -@media(min-width:768px){ - left:85px; -} + display: flex; + flex-direction: row; + align-items: center; + padding: 8px; + gap: 9px; + width: 200px; + z-index: 100; + height: 48px; + background: #ffffff; + border: 1px solid #bac4d6; + box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.05); + border-radius: 12px; + cursor: pointer; + position: absolute; + z-index: 100; + bottom: 45px; + + @media (max-width: 768px) { + right: 30px; + } + @media (min-width: 768px) { + left: 85px; + } `; const QROutline = styled(AiOutlineQrcode)` -width: 35px; -height: 30px; -` + width: 35px; + height: 30px; +`; const TextQR = styled.p` -font-family: 'Strawford'; -font-style: normal; -font-weight: 400; -font-size: 16px; -line-height: 140%; -text-align: center; -// color: #657795; + font-family: 'Strawford'; + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 140%; + text-align: center; + // color: #657795; `; const CreateGroupContainer = styled(ButtonV2)` flex-direction: row; align-self: stretch; - justify-content:flex-start + justify-content: flex-start; `; diff --git a/src/sections/space/SpaceFeedSection.tsx b/src/sections/space/SpaceFeedSection.tsx index f309fdccf6..94342ba9ff 100644 --- a/src/sections/space/SpaceFeedSection.tsx +++ b/src/sections/space/SpaceFeedSection.tsx @@ -12,7 +12,6 @@ import { Image } from 'components/SharedStyling'; import { ImageV2, ItemVV2 } from 'components/reusables/SharedStylingV2'; import { shortenText } from 'helpers/UtilityHelper'; import { SpaceContext } from 'contexts/SpaceContext'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { device } from 'config/Globals'; import { useNavigate } from 'react-router-dom'; import { SpaceComponentContext } from 'contexts/SpaceComponentsContext'; @@ -23,13 +22,14 @@ import { appConfig } from 'config'; // External imports import * as PushAPI from '@pushprotocol/restapi'; +import { AppContext } from 'contexts/AppContext'; const SpaceFeedSection = ({ spaceid }) => { const { SpaceFeedComponent, SpaceInvitesComponent, CreateSpaceComponent } = useContext(SpaceComponentContext); const { account } = useAccount(); const { spaceId ,setSpaceId, spaceInvites } = useContext(SpaceContext); - const { connectedUser } = useContext(ChatUserContext); + const { connectedUser } = useContext(AppContext); const theme = useTheme(); const isMobile = useMediaQuery(device.mobileL); diff --git a/src/sections/video/VideoCallSection.tsx b/src/sections/video/VideoCallSection.tsx index c65568c37d..9719d2ae53 100644 --- a/src/sections/video/VideoCallSection.tsx +++ b/src/sections/video/VideoCallSection.tsx @@ -6,15 +6,15 @@ import { LOADER_SPINNER_TYPE } from 'components/reusables/loaders/LoaderSpinner' import IncomingCall from 'components/video/IncomingCall'; import OutgoingOngoingCall from 'components/video/OutgoingOngoingCall'; import { VideoCallContext } from 'contexts/VideoCallContext'; -import { BlockedLoadingI } from 'types/chat'; -import { ChatUserContext } from 'contexts/ChatUserContext'; import { VideoCallStatus } from '@pushprotocol/restapi'; +import { AppContext } from 'contexts/AppContext'; +import { BlockedLoadingI } from 'types/context'; // Create Video Call const VideoCallSection = () => { const { videoCallData, createWrapper, requestWrapper, acceptRequestWrapper, disconnectWrapper, isCallAccepted } = useContext(VideoCallContext); - const { connectedUser, createUserIfNecessary } = useContext(ChatUserContext); + const { connectedUser, createUserIfNecessary } = useContext(AppContext); const [isLoading, setLoading] = useState(true); const [blockedLoading, setBlockedLoading] = useState({ diff --git a/src/structure/MasterInterfacePage.tsx b/src/structure/MasterInterfacePage.tsx index c23c99bb8a..126f3a7f7d 100644 --- a/src/structure/MasterInterfacePage.tsx +++ b/src/structure/MasterInterfacePage.tsx @@ -4,12 +4,14 @@ import React, { lazy, Suspense } from 'react'; // External Packages import { VscClose } from 'react-icons/vsc'; import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; -import { ToastContainer } from 'react-toastify'; +import { ToastContainer, toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.min.css'; import styled from 'styled-components'; +import { MdError } from 'react-icons/md'; +import useToast from 'hooks/useToast'; // Internal Components -import LoaderSpinner, { LOADER_TYPE } from 'components/reusables/loaders/LoaderSpinner'; +import LoaderSpinner, { LOADER_OVERLAY, LOADER_TYPE, PROGRESS_POSITIONING } from 'components/reusables/loaders/LoaderSpinner'; import ConnectedWalletRoute from '../components/ConnectedWalletRoute'; import { Anchor, Item } from '../primaries/SharedStyling'; const AirdropPage = lazy(() => import('pages/AirdropPage')); @@ -74,7 +76,7 @@ function MasterInterfacePage() { const [loadTeaserVideo, setLoadTeaserVideo] = React.useState(null); const location = useLocation(); - const { MetamaskPushSnapModalComponent }: AppContextType = React.useContext(AppContext); + const { MetamaskPushSnapModalComponent, blockedLoading }: AppContextType = React.useContext(AppContext); const { showMetamaskPushSnap } = React.useContext(AppContext); @@ -83,6 +85,7 @@ function MasterInterfacePage() { showMetamaskPushSnap(); } }, [location]); + const blockedLoadingToast = useToast(); // Render return ( @@ -148,7 +151,7 @@ function MasterInterfacePage() { element={} /> - + {/* } /> */} + {blockedLoading.errorMessage && ( + blockedLoadingToast.showMessageToast({ + toastTitle: 'Error', + toastMessage: blockedLoading.errorMessage, + toastType: 'ERROR', + getToastIcon: (size) => ( + + ), + }) + )} + + {blockedLoading.enabled && ( + + )} + {/* To play youtube video from anywhere */} {playTeaserVideo && ( diff --git a/src/types/chat.ts b/src/types/chat.ts index 6f2875b6e7..cee9cb6c76 100644 --- a/src/types/chat.ts +++ b/src/types/chat.ts @@ -1,3 +1,5 @@ +import { BlockedLoadingI } from "./context" + export interface MessageIPFS { fromCAIP10: string toCAIP10: string @@ -97,22 +99,12 @@ export interface TwitterFeedReturnType{ messageType:string; } - -export interface BlockedLoadingI { - enabled: boolean; - title: string; - spinnerEnabled?: boolean; - spinnerSize?: number; - spinnerType?: number; - progressEnabled?: boolean; - progress?: number; - progressNotice?: string; -} - - -export interface AppContext { +export interface ChatUserAppContext { currentChat: Feeds; + selectedChatId: string | undefined; + setSelectedChatId:(chatId: string | undefined) => void; viewChatBox: boolean; + setViewChatBox:(chatId: boolean) => void; receivedIntents: Feeds[]; setReceivedIntents: (rIntent: Feeds[]) => void; setChat: (feed: Feeds) => void; diff --git a/src/types/context.ts b/src/types/context.ts index 4415fbe9c8..5c38ac0d76 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -1,21 +1,63 @@ -import { PushAPI } from '@pushprotocol/restapi'; +import { ProgressHookType, PushAPI } from '@pushprotocol/restapi'; +import { ConnectedUser } from './chat'; +import { ModalType } from 'hooks/useModal'; export interface Web3NameListType { [key: string]: string; } +export interface onboardingProgressI { + enabled: boolean; + hookInfo: ProgressHookType; + spinnerType: number; + progress: number; + errorMessage?:string; +} + +export interface BlockedLoadingI { + enabled: boolean; + title: string; + spinnerEnabled?: boolean; + spinnerSize?: number; + spinnerType?: number; + progressEnabled?: boolean; + progress?: number; + progressNotice?: string; + errorMessage?:string; +} + +export interface LocalPeerType { + peer: string; + peerID: string; +} + +export interface ConnectedPeerIDType { + peerID: string; +} + export interface AppContextType { web3NameList: Web3NameListType; setWeb3NameList: (ens: Web3NameListType) => void; MetamaskPushSnapModalComponent: any; - showMetamaskPushSnap: any; + showMetamaskPushSnap: () => void; SnapState: number; - setSnapState: any; - initializePushSDK: any; + setSnapState: (SnapState: number) => void; + initializePushSDK: () => Promise; snapInstalled: boolean; - setSnapInstalled: (snapInstalled:boolean) => void; - handleConnectWallet: ( - showToast?: boolean, - toastMessage?: string - ) => void; + setSnapInstalled: (snapInstalled: boolean) => void; + handleConnectWallet: (showToast?: boolean, toastMessage?: string) => void; + setBlockedLoading: (blockedLoading: BlockedLoadingI) => void; + blockedLoading: BlockedLoadingI; + getUser: () => Promise; + connectedUser: ConnectedUser; + setConnectedUser: (connectedUser: ConnectedUser) => void; + pgpPvtKey: string; + setPgpPvtKey: (pgpPvtKey: string) => void; + localPeer: LocalPeerType; + setLocalPeer: (localPeer: LocalPeerType) => void; + connectedPeerID: ConnectedPeerIDType; + setConnectedPeerID: (connectedPeerID: ConnectedPeerIDType) => void; + displayQR: boolean; + setDisplayQR: (displayQR: boolean) => void; + createUserIfNecessary: () => Promise; } diff --git a/yarn.lock b/yarn.lock index 2bbdfe818d..e39c26d170 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5432,9 +5432,9 @@ __metadata: "@mui/icons-material": ^5.8.4 "@mui/lab": ^5.0.0-alpha.72 "@mui/material": ^5.5.0 - "@pushprotocol/restapi": 1.6.6 + "@pushprotocol/restapi": 0.0.1-alpha.64 "@pushprotocol/socket": 0.5.3 - "@pushprotocol/uiweb": 1.2.4 + "@pushprotocol/uiweb": 0.0.1-alpha.41 "@reduxjs/toolkit": ^1.7.1 "@testing-library/dom": ^6.12.2 "@testing-library/jest-dom": ^4.2.4 @@ -5621,9 +5621,9 @@ __metadata: languageName: node linkType: hard -"@pushprotocol/restapi@npm:1.6.6": - version: 1.6.6 - resolution: "@pushprotocol/restapi@npm:1.6.6" +"@pushprotocol/restapi@npm:0.0.1-alpha.64": + version: 0.0.1-alpha.64 + resolution: "@pushprotocol/restapi@npm:0.0.1-alpha.64" dependencies: "@ambire/signature-validator": ^1.3.1 "@metamask/eth-sig-util": ^5.0.2 @@ -5644,7 +5644,7 @@ __metadata: viem: ^1.20.3 peerDependencies: ethers: ^5.0.0 || ^6.0.0 - checksum: 1bd7c5ed6b5eeb423f962accf2c0e95750bfdefa0fc653e6b4d85b2616d70ee51bb7c43a696dfc9b9042924cfe716f0fe5675a3b92f9a8aee0301b2467e17296 + checksum: 6c62724de1522572de2dfc62212f7a461f8b92b4c8f32097d8a1cea527bda4e3d00b65ada8b2adb2a466d7615af7eb8092b28defed7dc06293a25ea3b9713503 languageName: node linkType: hard @@ -5672,9 +5672,9 @@ __metadata: languageName: node linkType: hard -"@pushprotocol/uiweb@npm:1.2.4": - version: 1.2.4 - resolution: "@pushprotocol/uiweb@npm:1.2.4" +"@pushprotocol/uiweb@npm:0.0.1-alpha.41": + version: 0.0.1-alpha.41 + resolution: "@pushprotocol/uiweb@npm:0.0.1-alpha.41" dependencies: "@livekit/components-react": ^1.2.2 "@livekit/components-styles": ^1.0.6 @@ -5706,7 +5706,7 @@ __metadata: axios: ^0.27.2 react: ">=16.8.0" styled-components: ^6.0.8 - checksum: 3cbc1f07691aaf3203c5ccc54f65eb9fcaa9a1310efc454c2512e83b2cbd75e4ae5f8f9bbba530da0bf416a1febf40e7e216ca16fc1312d662a6163ec0078713 + checksum: bbd07715409e0d22b17f825124202772f65169bbeec4c4b05cc4e5b9020e129957f78b3031549ec5c638046247375fecd8b3653c1dbc039363293763b4d7ba51 languageName: node linkType: hard