diff --git a/packages/examples/sdk-frontend-react/src/app/ChatSupportTest.tsx b/packages/examples/sdk-frontend-react/src/app/ChatSupportTest.tsx index 9b1fd70cd..905cd14ee 100644 --- a/packages/examples/sdk-frontend-react/src/app/ChatSupportTest.tsx +++ b/packages/examples/sdk-frontend-react/src/app/ChatSupportTest.tsx @@ -35,7 +35,7 @@ export const ChatSupportTest = () => { {
{ console.log("Chat id: ", chatid,chatParticipant) }} onUnreadCountChange={(count) => { console.log("Count is: ", count) }} onLoading={(loadingData) => { console.log("loading data: ", loadingData) }} onPaging={(chats) => { console.log("paging chats are: ", chats) }} onPreload={(chats) => { console.log("preload chats are: ", chats) }} - prefillChatPreviewList={prefill} + // prefillChatPreviewList={prefill} // listType='SEARCH' - // searchParamter='0x56A734ba4C7c7b117774C9aAcCEf521eBE66d65b' + // searchParamter='c2d544ad9d1efd5c5a593b143bf8232875c926cf28015564e70ad078b95f807e' />
diff --git a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatProfile.tsx b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatProfile.tsx index 3912db56d..e70b393ea 100644 --- a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatProfile.tsx +++ b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatProfile.tsx @@ -7,8 +7,8 @@ export const ChatProfileTest = () => { left component} chatProfileRightHelperComponent={
right component
} - chatId='4ac5ab85c9c3d57adbdf2dba79357e56b2f9ef0256befe750d9f93af78d2ca68' -// chatId='36baf37e441fdd94e23406c6c716fc4e91a93a9ee68e070cd5b054534dbe09a6' + chatId='monalisha.wallet' +// chatId='d9c2d6fa7132d49ea6d1b570f0ebd2bcc45c1ecac726eab993ad91c574fbe3c6' /> ) diff --git a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx index 72f09c750..397a1ff89 100644 --- a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx +++ b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewComponent.tsx @@ -14,13 +14,13 @@ const ChatViewComponentTest = () => {

Chat View Test page

- {/* {console.log('in close')}} /> */} + {console.log('in close')}} /> {/* {console.log('in close')}} modalBackground={MODAL_BACKGROUND_TYPE.OVERLAY} modalPositionType={MODAL_POSITION_TYPE.RELATIVE}/> */} console.log("Verification Failed")} - chatId='0x56A734ba4C7c7b117774C9aAcCEf521eBE66d65b' + chatId='0xf8250D363BD1F25f52F10C21188fe82c68C049c4' chatProfileLeftHelperComponent={console.debug('clicked')}/>} chatProfileRightHelperComponent={
right component
} diff --git a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewListTest.tsx b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewListTest.tsx index 85037aafe..400228016 100644 --- a/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewListTest.tsx +++ b/packages/examples/sdk-frontend-react/src/app/ChatUITest/ChatViewListTest.tsx @@ -25,7 +25,7 @@ const ChatViewListTest = () => { {/* */} - + {/* */} diff --git a/packages/restapi/package.json b/packages/restapi/package.json index 0dfa9775b..5076e42ce 100644 --- a/packages/restapi/package.json +++ b/packages/restapi/package.json @@ -1,6 +1,6 @@ { "name": "@pushprotocol/restapi", - "version": "1.7.2", + "version": "0.0.1-alpha.74", "type": "commonjs", "publishConfig": { "registry": "https://registry.npmjs.org/" diff --git a/packages/restapi/src/lib/pushNotification/PushNotificationTypes.ts b/packages/restapi/src/lib/pushNotification/PushNotificationTypes.ts index aee7b9955..c426f6871 100644 --- a/packages/restapi/src/lib/pushNotification/PushNotificationTypes.ts +++ b/packages/restapi/src/lib/pushNotification/PushNotificationTypes.ts @@ -127,12 +127,7 @@ export type ChannelOptions = { raw: boolean; }; -export type ChannelListOptions = { - page?: number; - limit?: number; - sort?: ChannelListSortType; - order?: ChannelListOrderType; -}; + export enum ChannelListType { ALL = 'all', @@ -144,7 +139,20 @@ export enum ChannelListSortType { SUBSCRIBER = 'subscribers', } + + +export type ChannelListOptions = { + page?: number; + limit?: number; + sort?: ChannelListSortType; + order?: ChannelListOrderType; +}; + + + + + export enum ChannelListOrderType { ASCENDING = 'asc', DESCENDING = 'desc', -} +}; \ No newline at end of file diff --git a/packages/uiweb/CHANGELOG.md b/packages/uiweb/CHANGELOG.md index fdbebbd08..a5a799e42 100644 --- a/packages/uiweb/CHANGELOG.md +++ b/packages/uiweb/CHANGELOG.md @@ -2,6 +2,65 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +## [1.1.15](https://github.com/push-protocol/push-sdk/compare/uiweb-0.0.1-alpha.44...uiweb-1.1.15) (2024-03-27) + + +### Bug Fixes + +* add doman in user profile and chat profile and copy ([#1171](https://github.com/push-protocol/push-sdk/issues/1171)) ([e981565](https://github.com/push-protocol/push-sdk/commit/e9815656f76f99d841e0895ec4fc283abd04db16)) +* added fetch chT ([c995efb](https://github.com/push-protocol/push-sdk/commit/c995efbac23cd5f20ca92c99763371345e54da95)) +* added fetching chat ([684f4e0](https://github.com/push-protocol/push-sdk/commit/684f4e0d6de96fb583cb8f0650f802e784c7871b)) +* added modify stream ([#1159](https://github.com/push-protocol/push-sdk/issues/1159)) ([15a3771](https://github.com/push-protocol/push-sdk/commit/15a3771e44c1abd923aee221422e943d1dae421e)) +* added settings name ([#1168](https://github.com/push-protocol/push-sdk/issues/1168)) ([62620ae](https://github.com/push-protocol/push-sdk/commit/62620ae7bc75f966b72f3058a8b4a08f40d6aa14)) +* class based done for chat viewlist messageInput ([b8e7b79](https://github.com/push-protocol/push-sdk/commit/b8e7b798ba955977635edda4311c9b484463d5f7)) +* converted messageInput to class based ([fbcf296](https://github.com/push-protocol/push-sdk/commit/fbcf2969779a993baabf21bc9c3079bf6d4e09c2)) +* converted send to class based ([b3daeaa](https://github.com/push-protocol/push-sdk/commit/b3daeaa0932826bad241cff4936ada82915f0b6d)) +* debugging stream issue ([0cf2092](https://github.com/push-protocol/push-sdk/commit/0cf2092f2745c0eb776d3d4be2d003866a31cc2b)) +* debugging stream issue ([5ea8fc4](https://github.com/push-protocol/push-sdk/commit/5ea8fc491d4f7259e1eb19b75c5d6b84ecf77704)) +* fix ([28f9a11](https://github.com/push-protocol/push-sdk/commit/28f9a11e4638134a582ea1c7a8b69d780cf4c3cf)) +* fixed ([862ab33](https://github.com/push-protocol/push-sdk/commit/862ab332c99d268d0318247486b7f7790707c56a)) +* fixed ([61a81db](https://github.com/push-protocol/push-sdk/commit/61a81db4d064736ca7f7302ea6e1d9059f378af1)) +* fixed chat bugs ([f4cdbda](https://github.com/push-protocol/push-sdk/commit/f4cdbdac6088cfc31b2b555038838bd5bb795f0c)) +* fixed chatpreview and widget issues ([ff6b576](https://github.com/push-protocol/push-sdk/commit/ff6b576ed969b328c29806966daee57b397f83a2)) +* fixed lint issues ([c13c171](https://github.com/push-protocol/push-sdk/commit/c13c171886970860de15ed0d4179949a436ef225)) +* fixed merge conflicts ([db2fd58](https://github.com/push-protocol/push-sdk/commit/db2fd5860ced139b5d5cc269e1cd518e52e4e180)) +* fixed minor bugs ([2b02a65](https://github.com/push-protocol/push-sdk/commit/2b02a65907659cecfbcdbf03e78b20b60a9021c1)) +* fixed search for chatId in chatpreview ([6e3cbc7](https://github.com/push-protocol/push-sdk/commit/6e3cbc7b924083fd71238c48029dbb291b56f29a)) +* fixed signer bug ([#1073](https://github.com/push-protocol/push-sdk/issues/1073)) ([0d3fd91](https://github.com/push-protocol/push-sdk/commit/0d3fd9124ce94d77efee86783f90de6aadbaea68)) +* fixed stream and pulled alpha ([06effe2](https://github.com/push-protocol/push-sdk/commit/06effe2a66845019cbe7390b799ecfe2cd0af341)) +* hack for stream fix ([7d89449](https://github.com/push-protocol/push-sdk/commit/7d89449b91870fc205aae66377103b86ab0a64b4)) +* horizontal scroll ([#1156](https://github.com/push-protocol/push-sdk/issues/1156)) ([8fb3301](https://github.com/push-protocol/push-sdk/commit/8fb3301146469df60eb32bef5703e3acb474101d)) +* Merge branch 'main' into alpha ([53a795d](https://github.com/push-protocol/push-sdk/commit/53a795db5ec82d44597410dca670dfadd9199277)) +* merged alpha ([fb0d5fa](https://github.com/push-protocol/push-sdk/commit/fb0d5fac604aafe2f2da7d8db32eaf8ee8823f38)) +* **migrate goerli to sepolia:** migrate goerli to sepolia ([#1149](https://github.com/push-protocol/push-sdk/issues/1149)) ([490b104](https://github.com/push-protocol/push-sdk/commit/490b104902b9a509c6a8c68d5c5f33446e91e113)) +* pulled main ([b7391b6](https://github.com/push-protocol/push-sdk/commit/b7391b6318b40117d61b86ea8163b116f757c94a)) +* removed event listeners ([3363fee](https://github.com/push-protocol/push-sdk/commit/3363fee687ad8fe894c8f851e723afa00c339578)) + + + +## [0.0.1-alpha.45](https://github.com/ethereum-push-notification-service/push-sdk/compare/uiweb-0.0.1-alpha.44...uiweb-0.0.1-alpha.45) (2024-03-07) + + +### Bug Fixes + +* added prefillChatList ([#1122](https://github.com/ethereum-push-notification-service/push-sdk/issues/1122)) ([8b00609](https://github.com/ethereum-push-notification-service/push-sdk/commit/8b006090d414c19f75a13ca782cde5dab0569b91)) +* fixed build issues ([f68a1ed](https://github.com/ethereum-push-notification-service/push-sdk/commit/f68a1edad6aa0b4c43511cd3f25cb08888f2a235)) +* fixed chat bugs ([f4cdbda](https://github.com/ethereum-push-notification-service/push-sdk/commit/f4cdbdac6088cfc31b2b555038838bd5bb795f0c)) +* fixed chatpreview ([25184de](https://github.com/ethereum-push-notification-service/push-sdk/commit/25184de7d505d72b1603e37b630d9ed205d479f5)) +* fixed chatpreview and widget issues ([ff6b576](https://github.com/ethereum-push-notification-service/push-sdk/commit/ff6b576ed969b328c29806966daee57b397f83a2)) +* fixed gues mode user profile ([f08725e](https://github.com/ethereum-push-notification-service/push-sdk/commit/f08725e27e5e6257cdaccd0634d706d4ce4de8b2)) +* fixed merge conflicts ([db2fd58](https://github.com/ethereum-push-notification-service/push-sdk/commit/db2fd5860ced139b5d5cc269e1cd518e52e4e180)) +* fixed minor bugs ([2b02a65](https://github.com/ethereum-push-notification-service/push-sdk/commit/2b02a65907659cecfbcdbf03e78b20b60a9021c1)) +* fixed minor issue ([841a2b7](https://github.com/ethereum-push-notification-service/push-sdk/commit/841a2b79e504af904aa99fc07b1d73c9e4f56b22)) +* fixed subscription error ([5431ff8](https://github.com/ethereum-push-notification-service/push-sdk/commit/5431ff849d7c01cbbb2511ebc9473d3d8548b2b3)) +* fixed support chat issues ([c63cbb8](https://github.com/ethereum-push-notification-service/push-sdk/commit/c63cbb8b64c20c2b84046beae7e3b6135ca9332e)) +* pulled alpha ([8d33691](https://github.com/ethereum-push-notification-service/push-sdk/commit/8d336911012e39bb0c4360820754230fa9b28a55)) +* stream connection support chat + pushUser to user fix ([#1066](https://github.com/ethereum-push-notification-service/push-sdk/issues/1066)) ([0ea4e02](https://github.com/ethereum-push-notification-service/push-sdk/commit/0ea4e026bceb38d3b37267b43709614cb1740472)) +* troubleshoot ([815c59a](https://github.com/ethereum-push-notification-service/push-sdk/commit/815c59a87deba30c8323a4d7d68f48bcedbbe730)) + + + +## [0.0.1-alpha.44](https://github.com/ethereum-push-notification-service/push-sdk/compare/uiweb-0.0.1-alpha.36...uiweb-0.0.1-alpha.44) (2024-02-13) ## [1.2.7](https://github.com/ethereum-push-notification-service/push-sdk/compare/uiweb-1.2.6...uiweb-1.2.7) (2024-03-11) diff --git a/packages/uiweb/package.json b/packages/uiweb/package.json index d191a2d3b..e7d2c5a62 100644 --- a/packages/uiweb/package.json +++ b/packages/uiweb/package.json @@ -1,6 +1,6 @@ { "name": "@pushprotocol/uiweb", - "version": "1.2.7", + "version": "1.1.15", "publishConfig": { "registry": "https://registry.npmjs.org/" }, diff --git a/packages/uiweb/src/lib/components/chat/ChatPreviewList/ChatPreviewList.tsx b/packages/uiweb/src/lib/components/chat/ChatPreviewList/ChatPreviewList.tsx index bdadad48e..1a37642ab 100644 --- a/packages/uiweb/src/lib/components/chat/ChatPreviewList/ChatPreviewList.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatPreviewList/ChatPreviewList.tsx @@ -19,7 +19,12 @@ import { Button, Section, Span, Spinner } from '../../reusables'; import { ChatPreview } from '../ChatPreview'; import useUserProfile from '../../../hooks/useUserProfile'; -import { getAddress, getNewChatUser, pCAIP10ToWallet } from '../../../helpers'; +import { + getAddress, + getNewChatUser, + pCAIP10ToWallet, + walletToPCAIP10, +} from '../../../helpers'; import { displayDefaultUser, generateRandomNonce, @@ -28,6 +33,7 @@ import { } from '../helpers'; import { IChatTheme } from '../theme'; import { ThemeContext } from '../theme/ThemeProvider'; +import useFetchChat from '../../../hooks/chat/useFetchChat'; // Define Interfaces /** @@ -92,21 +98,58 @@ export const ChatPreviewList: React.FC = ( badges: {}, }); - console.log(chatPreviewList); + //hack to fix stream + const [chatStream, setChatStream] = useState({}); // to track any new messages + const [chatAcceptStream, setChatAcceptStream] = useState({}); // to track any new messages + const [chatRequestStream, setChatRequestStream] = useState({}); // any message in request + const [groupCreateStream, setGroupCreateStream] = useState({}); // any message in request + // set theme const theme = useContext(ThemeContext); + const { fetchChat } = useFetchChat(); // set ref const listInnerRef = useRef(null); + // const { chatRequestStream, chatAcceptStream } = + // usePushChatStream(); + + //event listeners + usePushChatStream(); + + useEffect(() => { + window.addEventListener('chatStream', (e: any) => setChatStream(e.detail)); + window.addEventListener('chatAcceptStream', (e: any) => + setChatAcceptStream(e.detail) + ); + window.addEventListener('chatRequestStream', (e: any) => + setChatRequestStream(e.detail) + ); + window.addEventListener('groupCreateStream', (e: any) => + setGroupCreateStream(e.detail) + ); + return () => { + window.removeEventListener('chatStream', (e: any) => + setChatStream(e.detail) + ); + window.removeEventListener('chatAcceptStream', (e: any) => + setChatAcceptStream(e.detail) + ); + window.removeEventListener('chatRequestStream', (e: any) => + setChatRequestStream(e.detail) + ); + window.removeEventListener('groupCreateStream', (e: any) => + setGroupCreateStream(e.detail) + ); + }; + }, []); - const { chatStream, chatRequestStream, chatAcceptStream } = - usePushChatStream(); // Helper Functions // Add to chat items - const addChatItems: (items: IChatPreviewPayload[]) => void = ( - items: IChatPreviewPayload[] - ) => { + const addChatItems: ( + items: IChatPreviewPayload[], + incrementBadge?: boolean + ) => void = (items: IChatPreviewPayload[], incrementBadge?:boolean) => { const combinedItems: IChatPreviewPayload[] = [ ...items, ...chatPreviewList.items, @@ -119,19 +162,21 @@ export const ChatPreviewList: React.FC = ( ...prev, items: [...combinedItems], })); - - // increment badge for each item - items.forEach((item) => { - // only increment if not selected - if (chatPreviewListMeta.selectedChatId !== item.chatId) { - setBadge( - item.chatId!, - chatPreviewListMeta.badges[item.chatId!] - ? chatPreviewListMeta.badges[item.chatId!] + 1 - : 1 - ); - } - }); + if (incrementBadge) { + // increment badge for each item + items.forEach((item) => { + // only increment if not selected + if (chatPreviewListMeta.selectedChatId !== item.chatId) { + + setBadge( + item.chatId!, + chatPreviewListMeta.badges[item.chatId!] + ? chatPreviewListMeta.badges[item.chatId!] + 1 + : 1 + ); + } + }); + } }; // Remove from chat items @@ -151,6 +196,24 @@ export const ChatPreviewList: React.FC = ( }); }; + //Transform group creation stream + const transformGroupCreationStream: (item: any) => void = async ( + item: any + ) => { + const transformedItem: IChatPreviewPayload = { + chatId: item?.chatId, + chatPic: item?.meta.image, + chatParticipant: item?.meta.name, + chatGroup: true, + chatTimestamp: undefined, + chatMsg: { + messageType: '', + messageContent: '', + }, + }; + addChatItems([transformedItem],false); + }; + // Transform stream message const transformStreamMessage: (item: any) => void = async (item: any) => { if (!user) { @@ -185,7 +248,8 @@ export const ChatPreviewList: React.FC = ( } } // modify the chat items - addChatItems([modItem]); + console.debug('calling twice') + addChatItems([modItem],true); }; // Transform accepted request @@ -558,7 +622,7 @@ export const ChatPreviewList: React.FC = ( // Define stream objects useEffect(() => { if ( - Object.keys(chatStream).length > 0 && + Object.keys(chatStream || {}).length > 0 && chatStream.constructor === Object ) { if (options.listType === CONSTANTS.CHAT.LIST_TYPE.CHATS) { @@ -566,9 +630,29 @@ export const ChatPreviewList: React.FC = ( } } }, [chatStream]); + useEffect(() => { if ( - Object.keys(chatRequestStream).length > 0 && + Object.keys(groupCreateStream).length > 0 && + groupCreateStream.constructor === Object + ) { + if ( + options.listType === CONSTANTS.CHAT.LIST_TYPE.CHATS && + groupCreateStream.origin === 'self' + ) { + transformGroupCreationStream(groupCreateStream); + } else if ( + options.listType === CONSTANTS.CHAT.LIST_TYPE.REQUESTS && + groupCreateStream.origin === 'other' + ) { + transformGroupCreationStream(groupCreateStream); + } + } + }, [groupCreateStream]); + + useEffect(() => { + if ( + Object.keys(chatRequestStream || {}).length > 0 && chatRequestStream.constructor === Object ) { if ( @@ -584,9 +668,10 @@ export const ChatPreviewList: React.FC = ( } } }, [chatRequestStream]); + console.debug(chatStream, 'chat preview list chat stream event'); useEffect(() => { if ( - Object.keys(chatAcceptStream).length > 0 && + Object.keys(chatAcceptStream || {}).length > 0 && chatAcceptStream.constructor === Object ) { transformAcceptedRequest(chatAcceptStream); @@ -609,92 +694,112 @@ export const ChatPreviewList: React.FC = ( }; //check if searchParamter is there try { - if (options?.searchParamter) { - let formattedChatId: string | null = options?.searchParamter; - let userProfile: IUser | undefined = undefined; - let groupProfile: Group; - - //check if ens then convert to address - if (formattedChatId.includes('.')) { - const address = await getAddress(formattedChatId, env)!; - if (address) formattedChatId = pCAIP10ToWallet(address); - else { + if (options?.searchParamter) + if (options?.searchParamter) { + let formattedChatId: string | null = options?.searchParamter; + let userProfile: IUser | undefined = undefined; + let groupProfile: Group; + + if (formattedChatId.includes('.')) { + const address = await getAddress(formattedChatId, env)!; + if (address) formattedChatId = pCAIP10ToWallet(address); + else { + error = { + code: ChatPreviewListErrorCodes.CHAT_PREVIEW_LIST_INVALID_SEARCH_ERROR, + message: 'Invalid search', + }; + } + } + if (pCAIP10ToWallet(formattedChatId) == pCAIP10ToWallet(account!)) { error = { code: ChatPreviewListErrorCodes.CHAT_PREVIEW_LIST_INVALID_SEARCH_ERROR, message: 'Invalid search', }; } - } - if (!error) { - if (await ethers.utils.isAddress(formattedChatId)) { + + if (!error) { + const chatInfo = await fetchChat({ chatId: formattedChatId }); + + if (chatInfo && chatInfo?.meta?.group) + groupProfile = await getGroupByIDnew({ + groupId: formattedChatId, + }); + else if (account) + formattedChatId = pCAIP10ToWallet( + chatInfo?.participants.find( + (address) => address != walletToPCAIP10(account) + ) || formattedChatId + ); + //fetch profile - userProfile = await getNewChatUser({ - searchText: formattedChatId, - env, - fetchChatProfile: fetchUserProfile, - user, - }); - } else { - //fetch group info - groupProfile = await getGroupByIDnew({ groupId: formattedChatId }); - } - if (!userProfile && !groupProfile) { - error = { - code: ChatPreviewListErrorCodes.CHAT_PREVIEW_LIST_INVALID_SEARCH_ERROR, - message: 'Invalid search', - }; - } else { - searchedChat = { - ...searchedChat, - chatId: formattedChatId!, - chatGroup: !!groupProfile, - chatPic: - (userProfile?.profile?.picture ?? groupProfile?.groupImage) || - null, - chatParticipant: formattedChatId!, - }; - //fetch latest chat - const latestMessage = await fetchLatestMessage({ - chatId: formattedChatId, - }); - if (latestMessage) { + if (!groupProfile) { + userProfile = await getNewChatUser({ + searchText: formattedChatId, + env, + fetchChatProfile: fetchUserProfile, + user, + }); + } + + if (!userProfile && !groupProfile) { + error = { + code: ChatPreviewListErrorCodes.CHAT_PREVIEW_LIST_INVALID_SEARCH_ERROR, + message: 'Invalid search', + }; + } else { searchedChat = { ...searchedChat, - chatMsg: { - messageType: latestMessage[0]?.messageType, - messageContent: latestMessage[0]?.messageContent, - }, - chatTimestamp: latestMessage[0]?.timestamp, + chatId: chatInfo?.chatId || formattedChatId, + chatGroup: !!groupProfile, + chatPic: + (userProfile?.profile?.picture ?? groupProfile?.groupImage) || + null, + chatParticipant: groupProfile + ? groupProfile?.groupName + : formattedChatId!, }; + //fetch latest chat + const latestMessage = await fetchLatestMessage({ + chatId: formattedChatId, + }); + if (latestMessage) { + searchedChat = { + ...searchedChat, + chatMsg: { + messageType: latestMessage[0]?.messageType, + messageContent: latestMessage[0]?.messageContent, + }, + chatTimestamp: latestMessage[0]?.timestamp, + }; + } + + // return if nonce doesn't match or if page is not 1 + if ( + currentNonce !== chatPreviewList.nonce || + chatPreviewList.page !== 1 + ) { + return; + } + setChatPreviewList((prev) => ({ + nonce: generateRandomNonce(), + items: [...[searchedChat]], + page: 1, + preloading: false, + loading: false, + loaded: false, + reset: false, + resume: false, + errored: false, + error: null, + })); } - - // return if nonce doesn't match or if page is not 1 - if ( - currentNonce !== chatPreviewList.nonce || - chatPreviewList.page !== 1 - ) { - return; - } - setChatPreviewList((prev) => ({ - nonce: generateRandomNonce(), - items: [...[searchedChat]], - page: 1, - preloading: false, - loading: false, - loaded: false, - reset: false, - resume: false, - errored: false, - error: null, - })); } + } else { + error = { + code: ChatPreviewListErrorCodes.CHAT_PREVIEW_LIST_INSUFFICIENT_INPUT, + message: 'Insufficient input for search', + }; } - } else { - error = { - code: ChatPreviewListErrorCodes.CHAT_PREVIEW_LIST_INSUFFICIENT_INPUT, - message: 'Insufficient input for search', - }; - } if (error) { setChatPreviewList({ nonce: generateRandomNonce(), @@ -711,6 +816,7 @@ export const ChatPreviewList: React.FC = ( } } catch (e) { // return if nonce doesn't match + console.debug(e); console.debug( `Errored: currentNonce: ${currentNonce}, chatPreviewList.nonce: ${chatPreviewList.nonce}` ); @@ -788,18 +894,17 @@ export const ChatPreviewList: React.FC = ( selected={ options?.prefillChatPreviewList && options?.prefillChatPreviewList[index].selected - ? - options?.prefillChatPreviewList[index].selected - : - chatPreviewListMeta.selectedChatId === item.chatId ? true : false + ? options?.prefillChatPreviewList[index].selected + : chatPreviewListMeta.selectedChatId === item.chatId + ? true + : false } setSelected={ options?.prefillChatPreviewList && options?.prefillChatPreviewList[index].setSelected - ? - options?.prefillChatPreviewList[index].setSelected - : - setSelectedBadge} + ? options?.prefillChatPreviewList[index].setSelected + : setSelectedBadge + } /> ); })} diff --git a/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx b/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx index 01320356c..33d71f339 100644 --- a/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx @@ -26,7 +26,7 @@ import { allowedNetworks, device, } from '../../../config'; -import { getAddress, resolveNewEns, shortenText } from '../../../helpers'; +import { getAddress, pCAIP10ToWallet, resolveNewEns, shortenText, walletToPCAIP10 } from '../../../helpers'; import { formatAddress, isValidETHAddress } from '../helpers/helper'; import PublicChatIcon from '../../../icons/Public-Chat.svg'; import GreyImage from '../../../icons/greyImage.png'; @@ -34,6 +34,8 @@ import InfoIcon from '../../../icons/infodark.svg'; import VerticalEllipsisIcon from '../../../icons/VerticalEllipsis.svg'; import { TokenGatedSvg } from '../../../icons/TokenGatedSvg'; import useUserProfile from '../../../hooks/useUserProfile'; +import { ChatInfoResponse } from '../types'; +import useFetchChat from '../../../hooks/chat/useFetchChat'; export const ChatProfile: React.FC = ({ chatId, @@ -49,7 +51,9 @@ export const ChatProfile: React.FC = ({ // const [isGroup, setIsGroup] = useState(false); const [options, setOptions] = useState(false); - const [chatInfo, setChatInfo] = useState(); + const [formattedChatId, setFormattedChatId] = useState(''); + const [chatInfo, setChatInfo] = useState(null); + const [userInfo, setUserInfo] = useState(); const [groupInfo, setGroupInfo] = useState(); const [web3Name, setWeb3Name] = useState(null); const isMobile = useMediaQuery(device.tablet); @@ -59,6 +63,8 @@ export const ChatProfile: React.FC = ({ ); const DropdownRef = useRef(null); const [modal, setModal] = useState(false); + const { fetchChat } = useFetchChat(); + useClickAway(DropdownRef, () => { setOptions(false); @@ -69,54 +75,75 @@ export const ChatProfile: React.FC = ({ }; const fetchProfileData = async () => { - let formattedChatId; - if (chatId.includes('eip155:')) { - formattedChatId = chatId.replace('eip155:', ''); - } else if (chatId.includes('.')) { - formattedChatId = (await getAddress(chatId, env))!; - } else formattedChatId = chatId; - if (isValidETHAddress(formattedChatId)) { - const ChatProfile = await fetchUserProfile({ - profileId: formattedChatId, - env, - user, - }); - const result = await resolveNewEns(formattedChatId, provider, env); + + if (chatInfo && !chatInfo?.meta?.group && chatInfo?.participants && account) { + const recipient = pCAIP10ToWallet(chatInfo?.participants.find((address)=>address != walletToPCAIP10(account)) || formattedChatId); + const ChatProfile = await fetchUserProfile({ profileId: recipient, env,user }); + + // const ChatProfile = await fetchUserProfile({ + // profileId: formattedChatId, + // env, + // user, + // }); + const result = await resolveNewEns(recipient, provider, env); setWeb3Name(result); - setChatInfo(ChatProfile); + setUserInfo(ChatProfile); setGroupInfo(null); // setIsGroup(false); - } else { + } else if (chatInfo && chatInfo?.meta?.group) { const GroupProfile = await getGroupByIDnew({ groupId: formattedChatId }); setGroupInfo(GroupProfile); - setChatInfo(null); + setUserInfo(null); setWeb3Name(null); - // setIsGroup(true); } }; const getImage = () => { - if (chatInfo || groupInfo) { + if (userInfo || groupInfo) { return Object.keys(groupInfo || {}).length ? groupInfo?.groupImage ?? GreyImage - : chatInfo?.profile?.picture ?? - createBlockie?.(chatId)?.toDataURL()?.toString(); + : userInfo?.profile?.picture ?? + createBlockie?.(formattedChatId)?.toDataURL()?.toString(); } else { - return createBlockie?.(chatId)?.toDataURL()?.toString(); + return createBlockie?.(formattedChatId)?.toDataURL()?.toString(); } }; const getProfileName = () => { return Object.keys(groupInfo || {}).length ? shortenText(groupInfo?.chatId || '', 6, true) - : chatInfo - ? shortenText(chatInfo.did?.split(':')[1] ?? '', 6, true) + : userInfo + ? shortenText(userInfo.did?.split(':')[1] ?? '', 6, true) : shortenText(chatId?.split(':')[1], 6, true); }; + useEffect(() => { - if (!chatId) return; - fetchProfileData(); + + (async () => { + if (!user) return; + if(chatId){ + let formattedChatId; + if (chatId.includes('eip155:')) { + formattedChatId = chatId.replace('eip155:', ''); + } else if (chatId.includes('.')) { + formattedChatId = (await getAddress(chatId, env))!; + + } else formattedChatId = chatId; + setFormattedChatId(formattedChatId); + const chat = await fetchChat({ chatId: formattedChatId }); + if (Object.keys(chat || {}).length) { + setChatInfo(chat as ChatInfoResponse); + } + + } + + })(); }, [chatId, account, user]); + useEffect(() => { + (async () => { + await fetchProfileData(); + })(); + }, [chatInfo]); if (chatId) { return ( @@ -142,9 +169,9 @@ export const ChatProfile: React.FC = ({ wallet: getProfileName() as string, image: getImage(), web3Name: web3Name?web3Name:groupInfo?.groupName, - completeWallet:chatInfo?.wallets??groupInfo?.chatId + completeWallet:userInfo?.wallets??groupInfo?.chatId }} - copy={!!chatInfo|| !!groupInfo} + copy={!!userInfo|| !!groupInfo} customStyle={{ fontSize: theme?.fontWeight?.chatProfileText, textColor: theme?.textColor?.chatProfileText, diff --git a/packages/uiweb/src/lib/components/chat/ChatProfile/GroupInfoModal.tsx b/packages/uiweb/src/lib/components/chat/ChatProfile/GroupInfoModal.tsx index edc84ee61..19e08615f 100644 --- a/packages/uiweb/src/lib/components/chat/ChatProfile/GroupInfoModal.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatProfile/GroupInfoModal.tsx @@ -33,17 +33,22 @@ import { PENDING_MEMBERS_LIMIT, } from '../constants'; import { getRuleInfo } from '../helpers/getRulesToCondtionArray'; +import { Group } from '../exportedTypes'; import { - Group, - -} from '../exportedTypes'; -import { MODAL_BACKGROUND_TYPE, MODAL_POSITION_TYPE,ModalBackgroundType,ModalPositionType } from '../../../types'; + MODAL_BACKGROUND_TYPE, + MODAL_POSITION_TYPE, + ModalBackgroundType, + ModalPositionType, +} from '../../../types'; import { TokenGatedSvg } from '../../../icons/TokenGatedSvg'; import { GROUP_ROLES } from '../types'; import useGroupMemberUtilities from '../../../hooks/chat/useGroupMemberUtilities'; import useChatProfile from '../../../hooks/chat/useChatProfile'; -import { resolvePromisesSeq, transformIUserToChatMemberProfile } from '../helpers'; +import { + resolvePromisesSeq, + transformIUserToChatMemberProfile, +} from '../helpers'; import useUserProfile from '../../../hooks/useUserProfile'; export interface MemberPaginationData { @@ -245,7 +250,7 @@ type GroupInfoModalProps = { theme: IChatTheme; setModal: React.Dispatch>; groupInfo: Group; - setGroupInfo: React.Dispatch>; + setGroupInfo: React.Dispatch>; groupInfoModalBackground?: ModalBackgroundType; groupInfoModalPositionType?: ModalPositionType; }; @@ -270,7 +275,7 @@ const GroupInformation = ({ setShowAddMoreWalletModal, membersCount, }: GroupSectionProps) => { - const { account,user } = useChatData(); + const { account, user } = useChatData(); const [accountStatus, setAccountStatus] = useState( null ); @@ -403,7 +408,8 @@ const GroupInformation = ({ {accountStatus?.role === GROUP_ROLES.ADMIN.toLowerCase() && groupMembers?.accepted && - groupMembers?.accepted?.length < (groupInfo?.isPublic ? 25000 : 5000) && ( + groupMembers?.accepted?.length < + (groupInfo?.isPublic ? 25000 : 5000) && ( setShowAddMoreWalletModal(true)} @@ -449,6 +455,7 @@ const GroupInformation = ({ /> )} ({}); // to track any new messages + const [chatRejectStream, setChatRejectStream] = useState({}); // to track any rejected request + + const [participantRoleChangeStream, setParticipantRoleChangeStream] = + useState({}); // to track if a participant role is changed in a group + + const [participantRemoveStream, setParticipantRemoveStream] = useState( + {} + ); // to track if a participant is removed from group + const [participantLeaveStream, setParticipantLeaveStream] = useState({}); // to track if a participant leaves a group + const [participantJoinStream, setParticipantJoinStream] = useState({}); // to track if a participant joins a group + + const [groupUpdateStream, setGroupUpdateStream] = useState({}); + + //event listners + usePushChatStream(); + useEffect(() => { + window.addEventListener('chatAcceptStream', (e: any) => + setChatAcceptStream(e.detail) + ); + window.addEventListener('chatRejectStream', (e: any) => + setChatRejectStream(e.detail) + ); + window.addEventListener('participantRoleChangeStream', (e: any) => + setParticipantRoleChangeStream(e.detail) + ); + window.addEventListener('participantRemoveStream', (e: any) => + setParticipantRemoveStream(e.detail) + ); + window.addEventListener('participantLeaveStream', (e: any) => + setParticipantLeaveStream(e.detail) + ); + window.addEventListener('participantJoinStream', (e: any) => + setParticipantJoinStream(e.detail) + ); + window.addEventListener('groupUpdateStream', (e: any) => + setGroupUpdateStream(e.detail) + ); + return () => { + window.removeEventListener('chatAcceptStream', (e: any) => + setChatAcceptStream(e.detail) + ); + window.removeEventListener('chatRejectStream', (e: any) => + setChatRejectStream(e.detail) + ); + window.removeEventListener('participantRoleChangeStream', (e: any) => + setParticipantRoleChangeStream(e.detail) + ); + window.removeEventListener('participantRemoveStream', (e: any) => + setParticipantRemoveStream(e.detail) + ); + window.removeEventListener('participantLeaveStream', (e: any) => + setParticipantLeaveStream(e.detail) + ); + window.removeEventListener('participantJoinStream', (e: any) => + setParticipantJoinStream(e.detail) + ); + window.removeEventListener('groupUpdateStream', (e: any) => + setGroupUpdateStream(e.detail) + ); + }; + }, []); + + // const { + // chatAcceptStream, + // chatRejectStream, + // participantRemoveStream, + // participantLeaveStream, + // participantJoinStream, + // groupUpdateStream, + // participantRoleChangeStream, + // } = usePushChatStream(); //stream listeners useEffect(() => { if ( - Object.keys(chatAcceptStream).length > 0 && + Object.keys(chatAcceptStream || {}).length > 0 && chatAcceptStream.constructor === Object - ) - transformAcceptedRequest(chatAcceptStream); + ) + transformAcceptedRequest(chatAcceptStream); }, [chatAcceptStream]); useEffect(() => { if ( - Object.keys(chatRejectStream).length > 0 && + Object.keys(chatRejectStream || {}).length > 0 && chatRejectStream.constructor === Object - ) - transformRejectedRequest(chatRejectStream); + ) + transformRejectedRequest(chatRejectStream); }, [chatRejectStream]); useEffect(() => { if ( - Object.keys(participantRemoveStream).length > 0 && + Object.keys(participantRemoveStream || {}).length > 0 && participantRemoveStream.constructor === Object - ) - transformParticipantRemove(participantRemoveStream); + ) + transformParticipantRemove(participantRemoveStream); }, [participantRemoveStream]); useEffect(() => { if ( - Object.keys(participantLeaveStream).length > 0 && + Object.keys(participantLeaveStream || {}).length > 0 && participantLeaveStream.constructor === Object - ) - transformParticipantLeave(participantLeaveStream); + ) + transformParticipantLeave(participantLeaveStream); }, [participantLeaveStream]); useEffect(() => { (async () => { if ( - Object.keys(participantJoinStream).length > 0 && + Object.keys(participantJoinStream || {}).length > 0 && participantJoinStream.constructor === Object - ) - await transformParticipantJoin(participantJoinStream); + ) + await transformParticipantJoin(participantJoinStream); })(); - }, [participantJoinStream]); + useEffect(() => { if ( - Object.keys(groupUpdateStream).length > 0 && + Object.keys(groupUpdateStream || {}).length > 0 && groupUpdateStream.constructor === Object - ) - transformGroupDetails(groupUpdateStream); + ) + transformGroupDetails(groupUpdateStream); }, [groupUpdateStream]); useEffect(() => { if ( - Object.keys(participantRoleChangeStream).length > 0 && + Object.keys(participantRoleChangeStream || {}).length > 0 && participantRoleChangeStream.constructor === Object - ) - transformRoleChange(participantRoleChangeStream); + ) + transformRoleChange(participantRoleChangeStream); }, [participantRoleChangeStream]); useEffect(() => { (async () => { @@ -587,13 +658,12 @@ export const GroupInfoModal = ({ //add dependencies useEffect(() => { (async () => { - if(Object.keys(groupInfo || {}).length){ + if (Object.keys(groupInfo || {}).length) { setGroupMembers((prev) => ({ ...prev, loading: true })); await initialiseMemberPaginationData('pending', fetchPendingMembers); await initialiseMemberPaginationData('accepted', fetchAcceptedMembers); setGroupMembers((prev) => ({ ...prev, loading: false })); } - })(); }, [groupInfo]); @@ -622,7 +692,7 @@ export const GroupInfoModal = ({ //convert fetchPendingMembers and fetchAcceptedMembers to single method and show errors const fetchPendingMembers = async (page: number): Promise => { const fetchedPendingMembers = await fetchMembers({ - chatId: groupInfo!.chatId , + chatId: groupInfo!.chatId, page: page, limit: PENDING_MEMBERS_LIMIT, pending: true, @@ -636,7 +706,7 @@ export const GroupInfoModal = ({ ...prevMembers, pending: [ ...prevMembers!.pending, - ...(fetchedPendingMembers?.members || [] as ChatMemberProfile[]), + ...(fetchedPendingMembers?.members || ([] as ChatMemberProfile[])), ] .slice() .filter( @@ -644,8 +714,6 @@ export const GroupInfoModal = ({ index === self.findIndex((t) => t.address === item.address) ), })); - - }; const fetchAcceptedMembers = async (page: number): Promise => { const fetchedAcceptedMembers = await fetchMembers({ @@ -654,7 +722,6 @@ export const GroupInfoModal = ({ limit: ACCEPTED_MEMBERS_LIMIT, }); if (!fetchedAcceptedMembers?.members.length) - setAcceptedMemberPaginationData((prev: MemberPaginationData) => ({ ...prev, finishedFetching: true, @@ -663,7 +730,7 @@ export const GroupInfoModal = ({ ...prevMembers, accepted: [ ...prevMembers!.accepted, - ...(fetchedAcceptedMembers?.members || [] as ChatMemberProfile[]), + ...(fetchedAcceptedMembers?.members || ([] as ChatMemberProfile[])), ] .slice() .filter( @@ -671,7 +738,6 @@ export const GroupInfoModal = ({ index === self.findIndex((t) => t.address === item.address) ), })); - }; const initialiseMemberPaginationData = async ( @@ -718,9 +784,14 @@ export const GroupInfoModal = ({ ), })); }; - const memberRoleChange = (item:any): void => { - const acceptedMember:ChatMemberProfile[] = groupMembers?.accepted.map(member => member.address == item.to[0] ? {...member, role:item.newRole} : member); - console.debug(acceptedMember) + const memberRoleChange = (item: any): void => { + const acceptedMember: ChatMemberProfile[] = groupMembers?.accepted.map( + (member) => + member.address == item.to[0] + ? { ...member, role: item.newRole } + : member + ); + console.debug(acceptedMember); setGroupMembers((prevMembers: MembersType) => ({ ...prevMembers, accepted: acceptedMember, @@ -758,50 +829,50 @@ export const GroupInfoModal = ({ }; const transformParticipantJoin = async (item: any): Promise => { if (groupInfo?.chatId === item?.chatId) { - const profile = await fetchUserProfile({ profileId: item?.from,user }); - const transformedProfile = transformIUserToChatMemberProfile(profile,true); + const profile = await fetchUserProfile({ profileId: item?.from, user }); + const transformedProfile = transformIUserToChatMemberProfile( + profile, + true + ); addAcceptedMember([transformedProfile]); } }; - + // const transformRequestSent = async(item: any): Promise => { // if (item?.meta?.group && groupInfo?.chatId === item?.chatId) { - // const userPromises = item?.to.map((member:string) => + // const userPromises = item?.to.map((member:string) => // fetchChatProfile({ profileId: member}) // .then((userRecord) => { // return userRecord; // }) // .catch(console.error) // ); - // const users = await resolvePromisesSeq(userPromises); + // const users = await resolvePromisesSeq(userPromises); // const transformedUsers = users.map((user)=>{return transformIUserToChatMemberProfile(user,false)}); // addAcceptedMember(transformedUsers); // } // }; const transformRoleChange = (item: any): void => { - if ( groupInfo?.chatId === item?.chatId) { - memberRoleChange(item) - + if (groupInfo?.chatId === item?.chatId) { + memberRoleChange(item); } }; const transformGroupDetails = (item: any): void => { - if ( groupInfo?.chatId === item?.chatId) { + if (groupInfo?.chatId === item?.chatId) { const updatedGroupInfo = groupInfo; - if(updatedGroupInfo){ - updatedGroupInfo.groupName= item?.meta?.name; - updatedGroupInfo.groupDescription=item?.meta?.description; - updatedGroupInfo.groupImage=item?.meta?.image; - updatedGroupInfo.groupCreator=item?.meta?.owner; - updatedGroupInfo.isPublic=!item?.meta?.private; - updatedGroupInfo.rules=item?.meta?.rules; + if (updatedGroupInfo) { + updatedGroupInfo.groupName = item?.meta?.name; + updatedGroupInfo.groupDescription = item?.meta?.description; + updatedGroupInfo.groupImage = item?.meta?.image; + updatedGroupInfo.groupCreator = item?.meta?.owner; + updatedGroupInfo.isPublic = !item?.meta?.private; + updatedGroupInfo.rules = item?.meta?.rules; setGroupInfo(updatedGroupInfo); } - } }; - const callMembers = async ( page: number, setMemberPaginationData: React.Dispatch< diff --git a/packages/uiweb/src/lib/components/chat/ChatProfile/PendingMembers.tsx b/packages/uiweb/src/lib/components/chat/ChatProfile/PendingMembers.tsx index 25b7f3a13..e389cb853 100644 --- a/packages/uiweb/src/lib/components/chat/ChatProfile/PendingMembers.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatProfile/PendingMembers.tsx @@ -44,6 +44,7 @@ type AcceptedMembersProps = { >; acceptedMembers: ChatMemberProfile[]; chatId: string; + theme: IChatTheme; }; const UPDATE_KEYS = { @@ -89,7 +90,6 @@ export const PendingMembers = ({ })); // eslint-disable-next-line no-use-before-define }, [isInViewportPending]); - if (pendingMembers && pendingMembers.length) { return ( @@ -115,7 +115,8 @@ export const PendingMembers = ({ maxHeight="10rem" overflow="hidden auto" justifyContent="start" - borderRadius="16px" + borderRadius="12px" + theme={theme} > {showPendingRequests && pendingMembers && @@ -143,7 +144,7 @@ export const PendingMembers = ({ ))} {pendingMemberPaginationData.loading && (
- +
)}
@@ -160,6 +161,7 @@ export const AcceptedMembers = ({ setAcceptedMemberPaginationData, acceptedMemberPaginationData, chatId, + theme, }: AcceptedMembersProps) => { const { account } = useChatData(); const acceptedMemberPageRef = useRef(null); @@ -302,7 +304,6 @@ export const AcceptedMembers = ({ }; useClickAway(dropdownRef, () => setSelectedMemberAddress(null)); - console.debug(acceptedMembers); if (acceptedMembers && acceptedMembers.length) { return ( {acceptedMembers.map((item, index) => (
{acceptedMemberPaginationData.loading && (
- +
)} @@ -393,6 +395,16 @@ const Badge = styled.div` font-weight: 700; `; -const ProfileSection = styled(Section)` +const ProfileSection = styled(Section)<{ theme: IChatTheme }>` height: fit-content; + &::-webkit-scrollbar-thumb { + background: transparent; + border-radius: 10px; + } + &::-webkit-scrollbar-button { + height: 20px; + } + &::-webkit-scrollbar { + width: 0px; + } `; diff --git a/packages/uiweb/src/lib/components/chat/ChatViewList/ApproveRequestBubble.tsx b/packages/uiweb/src/lib/components/chat/ChatViewList/ApproveRequestBubble.tsx index 8c8e2ea36..231f3b7a6 100644 --- a/packages/uiweb/src/lib/components/chat/ChatViewList/ApproveRequestBubble.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatViewList/ApproveRequestBubble.tsx @@ -6,6 +6,9 @@ import useApproveChatRequest from '../../../hooks/chat/useApproveChatRequest'; import { useChatData } from '../../../hooks'; import styled from 'styled-components'; import { IChatTheme } from '../theme'; +import { Group } from '../exportedTypes'; +import useToast from '../reusables/NewToast'; +import { MdCheckCircle } from 'react-icons/md'; /** * @interface IThemeProps @@ -16,26 +19,25 @@ interface IThemeProps { } export interface IApproveRequestBubbleProps { chatId: string; - chatFeed: IFeeds; - setChatFeed: Dispatch; + groupInfo?: Group | null; } export const ApproveRequestBubble = ({ - chatFeed, + groupInfo = null, chatId, - setChatFeed, }: IApproveRequestBubbleProps) => { const { pgpPrivateKey } = useChatData(); const ApproveRequestText = { - GROUP: `You were invited to the group ${chatFeed?.groupInformation?.groupName}. Please accept to continue messaging in this group.`, + GROUP: `You were invited to the group ${groupInfo?.groupName}. Please accept to continue messaging in this group.`, W2W: ` Please accept to enable push chat from this wallet`, }; const theme = useContext(ThemeContext); const { approveChatRequest, loading: approveLoading } = useApproveChatRequest(); + const approveToast = useToast(); const handleApproveChatRequest = async () => { try { @@ -46,11 +48,14 @@ export const ApproveRequestBubble = ({ const response = await approveChatRequest({ chatId, }); + if (response) { - const updatedChatFeed = { ...(chatFeed as IFeeds) }; - updatedChatFeed.intent = response; - - setChatFeed(updatedChatFeed); + approveToast.showMessageToast({ + toastTitle: 'Success', + toastMessage: 'Group Invitation sent', + toastType: 'SUCCESS', + getToastIcon: (size) => , + }); } } catch (error_: Error | any) { console.log(error_.message); @@ -80,7 +85,7 @@ export const ApproveRequestBubble = ({ color={theme.textColor?.chatReceivedBubbleText} lineHeight="24px" > - {chatFeed?.groupInformation + {groupInfo ? ApproveRequestText.GROUP : ApproveRequestText.W2W} diff --git a/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx b/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx index 2ce62577a..c845676bc 100644 --- a/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx @@ -1,39 +1,39 @@ import React, { useContext, useEffect, useRef, useState } from 'react'; import { - GroupDTO, - IFeeds, IMessageIPFS, IMessageIPFSWithCID, + IUser, } from '@pushprotocol/restapi'; import moment from 'moment'; import styled from 'styled-components'; +import { ToastContainer } from 'react-toastify'; +import { MdError } from 'react-icons/md'; import { chatLimit } from '../../../config'; import { appendUniqueMessages, - checkIfIntent, - checkIfSameChat, dateToFromNowDaily, - getDefaultFeedObject, - getNewChatUser, pCAIP10ToWallet, walletToPCAIP10, } from '../../../helpers'; -import { useChatData, usePushChatSocket } from '../../../hooks'; +import { useChatData, usePushChatStream } from '../../../hooks'; import useFetchMessageUtilities from '../../../hooks/chat/useFetchMessageUtilities'; import { Section, Span, Spinner } from '../../reusables'; import { ChatViewBubble } from '../ChatViewBubble'; -import { IChatViewListProps } from '../exportedTypes'; -import { IGroup, Messagetype } from '../../../types'; +import { Group, IChatViewListProps } from '../exportedTypes'; import { IChatTheme } from '../theme'; import { ThemeContext } from '../theme/ThemeProvider'; import useFetchChat from '../../../hooks/chat/useFetchChat'; -import useGetGroup from '../../../hooks/chat/useGetGroup'; -import useGetChatProfile from '../../../hooks/useGetChatProfile'; import { ApproveRequestBubble } from './ApproveRequestBubble'; import { ENCRYPTION_KEYS, EncryptionMessage } from './MessageEncryption'; +import useGroupMemberUtilities from '../../../hooks/chat/useGroupMemberUtilities'; +import { ChatInfoResponse } from '../types'; +import useUserProfile from '../../../hooks/useUserProfile'; +import useGetGroupByIDnew from '../../../hooks/chat/useGetGroupByIDnew'; +import useToast from '../reusables/NewToast'; +import { checkIfNewRequest, transformStreamToIMessageIPFSWithCID } from '../helpers'; /** * @interface IThemeProps @@ -52,179 +52,271 @@ export const ChatViewList: React.FC = ( options: IChatViewListProps ) => { const { chatId, limit = chatLimit, chatFilterList = [] } = options || {}; - const { pgpPrivateKey, account, connectedProfile, setConnectedProfile } = - useChatData(); - const [chatFeed, setChatFeed] = useState({} as IFeeds); + const { account, user } = useChatData(); + const [chatInfo, setChatInfo] = useState(null); + const [groupInfo, setGroupInfo] = useState(null); + const [userInfo, setUserInfo] = useState(null); + const [chatStatusText, setChatStatusText] = useState(''); - const [messages, setMessages] = useState(); + const [messages, setMessages] = useState([]); const [loading, setLoading] = useState(true); - const [conversationHash, setConversationHash] = useState(); const { historyMessages, historyLoading: messageLoading } = - useFetchMessageUtilities(); + useFetchMessageUtilities(); const listInnerRef = useRef(null); const [isMember, setIsMember] = useState(false); const { fetchChat } = useFetchChat(); - const { fetchChatProfile } = useGetChatProfile(); - const { getGroup } = useGetGroup(); - - const { messagesSinceLastConnection, groupInformationSinceLastConnection } = - usePushChatSocket(); + const { fetchUserProfile } = useUserProfile(); + const { getGroupByIDnew } = useGetGroupByIDnew(); + const { fetchMemberStatus } = useGroupMemberUtilities(); + const chatViewListToast = useToast(); + + //hack for stream not working + const [chatStream, setChatStream] = useState({}); // to track any new messages + const [chatRequestStream, setChatRequestStream] = useState({}); // to track any new messages + + const [chatAcceptStream, setChatAcceptStream] = useState({}); // to track any new messages + const [participantRemoveStream, setParticipantRemoveStream] = useState( + {} + ); // to track if a participant is removed from group + const [participantLeaveStream, setParticipantLeaveStream] = useState({}); // to track if a participant leaves a group + const [participantJoinStream, setParticipantJoinStream] = useState({}); // to track if a participant joins a group + + const [groupUpdateStream, setGroupUpdateStream] = useState({}); + // const { + // chatStream, + // groupUpdateStream, + // chatAcceptStream, + // participantJoinStream, + // participantLeaveStream, + // participantRemoveStream, + // } = usePushChatStream(); + + //event listeners + usePushChatStream(); + useEffect(() => { + window.addEventListener('chatStream', (e: any) => setChatStream(e.detail)); + window.addEventListener('chatRequestStream', (e: any) => setChatRequestStream(e.detail)); + window.addEventListener('chatAcceptStream', (e: any) => + setChatAcceptStream(e.detail) + ); + window.addEventListener('participantRemoveStream', (e: any) => + setParticipantRemoveStream(e.detail) + ); + window.addEventListener('participantLeaveStream', (e: any) => + setParticipantLeaveStream(e.detail) + ); + window.addEventListener('participantJoinStream', (e: any) => + setParticipantJoinStream(e.detail) + ); + window.addEventListener('groupUpdateStream', (e: any) => + setGroupUpdateStream(e.detail) + ); + return () => { + window.removeEventListener('chatStream', (e: any) => + setChatStream(e.detail) + ); + window.removeEventListener('chatRequestStream', (e: any) => setChatRequestStream(e.detail)); + + window.removeEventListener('chatAcceptStream', (e: any) => + setChatAcceptStream(e.detail) + ); + window.removeEventListener('participantRemoveStream', (e: any) => + setParticipantRemoveStream(e.detail) + ); + window.removeEventListener('participantLeaveStream', (e: any) => + setParticipantLeaveStream(e.detail) + ); + window.removeEventListener('participantJoinStream', (e: any) => + setParticipantJoinStream(e.detail) + ); + window.removeEventListener('groupUpdateStream', (e: any) => + setGroupUpdateStream(e.detail) + ); + }; + }, []); const theme = useContext(ThemeContext); const dates = new Set(); const { env } = useChatData(); - useEffect(() => { setChatStatusText(''); - }, [chatId, account, env]); + }, [chatId, account, env, user]); + + useEffect(() => { + setChatInfo(null); + setMessages([]); + setGroupInfo(null); + }, [chatId, account, user, env]); useEffect(() => { (async () => { - if (!connectedProfile && account) { - const user = await fetchChatProfile({ profileId: account!, env }); - if (user) setConnectedProfile(user); + if (!user) return; + if (chatId) { + const chat = await fetchChat({ chatId: chatId }); + if (Object.keys(chat || {}).length) { + setChatInfo(chat as ChatInfoResponse); + } + + setLoading(false); } })(); - }, [account]); - useEffect(() => { - setConversationHash(undefined); - setChatFeed({} as IFeeds); - setMessages(undefined); - - - }, [chatId, account, pgpPrivateKey, env]); - - //need to make a common method for fetching chatFeed to ruse in messageInput + }, [chatId, user, account, env]); useEffect(() => { (async () => { - if (!account && !env) return; - const chat = await fetchChat({ chatId:chatId }); - if (Object.keys(chat || {}).length) { - setConversationHash(chat?.threadhash as string); - setChatFeed(chat as IFeeds); - } - else { - let newChatFeed; - let group; - const result = await getNewChatUser({ - searchText: chatId, - fetchChatProfile, + let UserProfile, GroupProfile; + if ( + chatInfo && + !chatInfo?.meta?.group && + chatInfo?.participants && + account + ) { + UserProfile = await fetchUserProfile({ + profileId: pCAIP10ToWallet( + chatInfo?.participants.find( + (address) => address != walletToPCAIP10(account) + ) || chatId + ), env, + user, }); - if (result) { - newChatFeed = getDefaultFeedObject({ user: result }); - } else { - group = await getGroup({ searchText: chatId }); - if (group) { - newChatFeed = getDefaultFeedObject({ groupInformation: group }); - } - } - if (newChatFeed) { - if (!newChatFeed?.groupInformation) { - setChatStatusText(ChatStatus.FIRST_CHAT); - } - setConversationHash(newChatFeed.threadhash as string); - setChatFeed(newChatFeed); - } else { + if (UserProfile) setUserInfo(UserProfile); + setChatStatusText(ChatStatus.FIRST_CHAT); + } else if (chatInfo && chatInfo?.meta?.group) { + GroupProfile = await getGroupByIDnew({ groupId: chatId }); + if (GroupProfile) setGroupInfo(GroupProfile); + else { setChatStatusText(ChatStatus.INVALID_CHAT); } } - setLoading(false); })(); + }, [chatInfo]); - }, [chatId, pgpPrivateKey, account, env]); + //moniters stream changes + useEffect(() => { + if ( + Object.keys(chatAcceptStream || {}).length > 0 && + chatAcceptStream.constructor === Object + ) { + const updatedChatInfo = { ...(chatInfo as ChatInfoResponse) }; + if (updatedChatInfo) updatedChatInfo.list = 'CHATS'; + setChatInfo(updatedChatInfo); + } + }, [chatAcceptStream]); + useEffect(() => { + if ( + Object.keys(chatStream || {}).length > 0 && + chatStream.constructor === Object + ) { + transformSteamMessage(chatStream); + setChatStatusText(''); + scrollToBottom(); + } + }, [chatStream]); - //moniters socket changes useEffect(() => { - if (checkIfSameChat(messagesSinceLastConnection, account!, chatId)) { - const updatedChatFeed = chatFeed; - updatedChatFeed.msg = messagesSinceLastConnection; - if (!Object.keys(messages || {}).length) { - - setFilteredMessages([ - messagesSinceLastConnection, - ] as IMessageIPFSWithCID[]); - setConversationHash(messagesSinceLastConnection.cid); - } else { - const newChatViewList = appendUniqueMessages( - messages as Messagetype, - [messagesSinceLastConnection], - false - ); - setFilteredMessages(newChatViewList as IMessageIPFSWithCID[]); - } + if ( + Object.keys(chatRequestStream || {}).length > 0 && + chatRequestStream.constructor === Object + ) { + transformSteamMessage(chatRequestStream); setChatStatusText(''); - setChatFeed(updatedChatFeed); scrollToBottom(); } - }, [messagesSinceLastConnection]); + }, [chatRequestStream]); - // remove fetching group once stream comes useEffect(() => { - if (Object.keys(groupInformationSinceLastConnection || {}).length) { - if ( - chatFeed?.groupInformation?.chatId.toLowerCase() === - groupInformationSinceLastConnection.chatId.toLowerCase() - ) { - (async()=>{ - const updateChatFeed = chatFeed; - const group:IGroup | undefined = await getGroup({ searchText: chatId }); - if (group || !!Object.keys(group || {}).length){ - updateChatFeed.groupInformation = group! as GroupDTO ; - - setChatFeed(updateChatFeed); - } - - })(); - + if ( + Object.keys(groupUpdateStream || {}).length > 0 && + groupUpdateStream.constructor === Object + ) + transformGroupDetails(groupUpdateStream); + }, [groupUpdateStream]); + + const transformSteamMessage = (item: any) => { + if (!user) { + return; + } + if (chatInfo && ((item?.chatId == chatInfo?.chatId) || checkIfNewRequest(item,chatId))) { + const transformedMessage = transformStreamToIMessageIPFSWithCID(item); + if (messages && messages.length) { + const newChatViewList = appendUniqueMessages( + messages, + [transformedMessage], + false + ); + setFilteredMessages(newChatViewList); + } else { + setFilteredMessages([transformedMessage]); } } - }, [groupInformationSinceLastConnection]); + }; + const transformGroupDetails = (item: any): void => { + if (groupInfo?.chatId === item?.chatId) { + const updatedGroupInfo = groupInfo; + if (updatedGroupInfo) { + updatedGroupInfo.groupName = item?.meta?.name; + updatedGroupInfo.groupDescription = item?.meta?.description; + updatedGroupInfo.groupImage = item?.meta?.image; + updatedGroupInfo.groupCreator = item?.meta?.owner; + updatedGroupInfo.isPublic = !item?.meta?.private; + updatedGroupInfo.rules = item?.meta?.rules; + setGroupInfo(updatedGroupInfo); + } + } + }; useEffect(() => { - if (conversationHash) { + if (chatInfo) { (async function () { await getMessagesCall(); })(); } - }, [conversationHash, pgpPrivateKey, account, env,chatFeed, chatId]); - - + }, [chatInfo, user?.readmode(), account, env, chatId]); useEffect(() => { - if ( - conversationHash && - Object.keys(messages || {}).length && - messages?.messages.length && - messages?.messages.length <= limit - ) { + if (messages && messages?.length && messages?.length <= limit) { setChatStatusText(''); scrollToBottom(); } }, [messages]); - useEffect(()=>{ - - if(chatFeed && !chatFeed?.groupInformation?.isPublic && account) - { - chatFeed?.groupInformation?.members.forEach((acc) => { - if ( - acc.wallet.toLowerCase() === walletToPCAIP10(account!).toLowerCase() - ) { - setIsMember(true); + useEffect(() => { + if (user && account && groupInfo) { + (async () => { + const status = await fetchMemberStatus({ + chatId: groupInfo.chatId!, + accountId: account, + }); + if (status && typeof status !== 'string') { + setIsMember(status?.participant); + } else { + //show toast + chatViewListToast.showMessageToast({ + toastTitle: 'Error', + toastMessage: 'Error in fetching member details', + toastType: 'ERROR', + getToastIcon: (size) => , + }); } - }); + })(); } - },[account,chatFeed]) + }, [ + account, + groupInfo, + chatInfo, + chatAcceptStream, + participantJoinStream, + participantLeaveStream, + participantRemoveStream, + ]); //methods const scrollToBottom = () => { - setTimeout(()=>{ + setTimeout(() => { if (listInnerRef.current) { - listInnerRef.current.scrollTop = listInnerRef.current.scrollHeight +100; - + listInnerRef.current.scrollTop = + listInnerRef.current.scrollHeight + 100; } - },0) - + }, 0); }; const onScroll = async () => { @@ -244,33 +336,27 @@ export const ChatViewList: React.FC = ( }; const getMessagesCall = async () => { - let threadHash = null; - if (!messages) { - threadHash = conversationHash; - } else { - threadHash = messages?.lastThreadHash; + let reference = null; + if (messages && messages?.length) { + reference = messages[0].link; } - if ( - threadHash && - ((account && pgpPrivateKey&& chatFeed && !chatFeed?.groupInformation) || - (chatFeed && chatFeed?.groupInformation)) - ) { - + + if (user) { const chatHistory = await historyMessages({ limit: limit, - threadHash, + chatId, + reference, }); if (chatHistory?.length) { - if (Object.keys(messages || {}) && messages?.messages.length) { + if (messages && messages?.length) { const newChatViewList = appendUniqueMessages( messages, - chatHistory, + chatHistory.reverse(), true ); setFilteredMessages(newChatViewList as IMessageIPFSWithCID[]); } else { - - setFilteredMessages(chatHistory as IMessageIPFSWithCID[]); + setFilteredMessages(chatHistory.reverse() as IMessageIPFSWithCID[]); } } } @@ -282,22 +368,15 @@ export const ChatViewList: React.FC = ( ); if (updatedMessageList && updatedMessageList.length) { - setMessages({ - messages: updatedMessageList, - lastThreadHash: updatedMessageList[0].link, - }); + setMessages([...updatedMessageList]); } }; - - const ifBlurChat = () =>{ - + const ifBlurChat = () => { return !!( - chatFeed && - chatFeed?.groupInformation && - !chatFeed?.groupInformation?.isPublic && - ((!isMember && pgpPrivateKey) || (!pgpPrivateKey)) + user && + ((groupInfo && !groupInfo?.isPublic && !isMember) || user?.readmode()) ); - } + }; type RenderDataType = { chat: IMessageIPFS; @@ -324,12 +403,11 @@ export const ChatViewList: React.FC = ( flexDirection="column" ref={listInnerRef} width="100%" + height="100%" justifyContent="start" padding="0 2px" theme={theme} - blur={ - ifBlurChat() - } + blur={ifBlurChat()} onScroll={(e) => { e.stopPropagation(); onScroll(); @@ -338,15 +416,13 @@ export const ChatViewList: React.FC = ( {loading ? : ''} {!loading && ( <> - {chatFeed && - (chatFeed.publicKey || - (chatFeed?.groupInformation && - !chatFeed?.groupInformation?.isPublic)) ? ( + {(userInfo && userInfo.publicKey) || + (groupInfo && !groupInfo?.isPublic) ? ( ) : ( = ( justifyContent="start" width="100%" > - {messages?.messages && - messages?.messages?.map( - (chat: IMessageIPFS, index: number) => { - const dateNum = moment(chat.timestamp).format('L'); - const position = - pCAIP10ToWallet(chat.fromDID).toLowerCase() !== - account?.toLowerCase() - ? 0 - : 1; - return ( - <> - {dates.has(dateNum) - ? null - : renderDate({ chat, dateNum })} -
- -
- - ); - } - )} + {messages && + messages?.map((chat: IMessageIPFS, index: number) => { + const dateNum = moment(chat.timestamp).format('L'); + const position = + pCAIP10ToWallet(chat.fromDID)?.toLowerCase() !== + account?.toLowerCase() + ? 0 + : 1; + return ( + <> + {dates.has(dateNum) + ? null + : renderDate({ chat, dateNum })} +
+ +
+ + ); + })} - {!!Object.keys(chatFeed || {}).length && - account && - checkIfIntent({ - chat: chatFeed as IFeeds, - account: account!, - }) && ( - - )} + {chatInfo && chatInfo?.list === 'REQUESTS' && ( + + )} } )} + ); }; @@ -436,4 +505,3 @@ const ChatViewListCard = styled(Section)` overscroll-behavior: contain; scroll-behavior: smooth; `; - diff --git a/packages/uiweb/src/lib/components/chat/CreateGroup/AddCriteria.tsx b/packages/uiweb/src/lib/components/chat/CreateGroup/AddCriteria.tsx index 1d83af289..f99fa58b2 100644 --- a/packages/uiweb/src/lib/components/chat/CreateGroup/AddCriteria.tsx +++ b/packages/uiweb/src/lib/components/chat/CreateGroup/AddCriteria.tsx @@ -27,7 +27,7 @@ import BSCSvg from '../../../icons/bsc.svg'; import FuseSvg from '../../../icons/fuse.svg'; import OptimismSvg from '../../../icons/optimisim.svg'; -import { BLOCKCHAIN_NETWORK, device } from '../../../config'; +import { BLOCKCHAIN_NETWORK, ENV, device } from '../../../config'; import { GUILD_COMPARISON_OPTIONS, INVITE_CHECKBOX_LABEL } from '../constants'; import { CATEGORY, @@ -252,14 +252,19 @@ const AddCriteria = ({ icon: FuseSvg, function: () => setSelectedChainValue(5), }, - { + + ]; + if(env !== ENV.PROD) + { + + dropdownChainsValues.push( { id: 6, value: BLOCKCHAIN_NETWORK[env].BERACHAIN, title: 'Berachain', icon: BerachainSvg, - function: () => setSelectedChainValue(46), - }, - ]; + function: () => setSelectedChainValue(6), + } as DropdownValueType) + } const onQuantityChange = (e: any) => { setQuantity({ ...quantity, value: e.target.value }); diff --git a/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx b/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx index 3042d7818..7534d0a13 100644 --- a/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx +++ b/packages/uiweb/src/lib/components/chat/CreateGroup/CreateGroupModal.tsx @@ -332,6 +332,12 @@ const CreateGroupDetail = ({ }); return; } + if (groupName.trim().length <3) { + setValidationErrors({ + groupName: 'Group name should have minimum 3 character', + }); + return; + } // verify description if (groupDescription.trim().length === 0) { @@ -340,6 +346,12 @@ const CreateGroupDetail = ({ }); return; } + if (groupDescription.trim().length <3) { + setValidationErrors({ + groupDescription: 'Group Description should have minimum 3 character', + }); + return; + } } if (handleNext) { @@ -404,7 +416,7 @@ const CreateGroupDetail = ({
setGroupInputDetails((prev: GroupInputDetailsType) => ({ @@ -421,7 +433,7 @@ const CreateGroupDetail = ({