diff --git a/packages/examples/boilerplate/index.js b/packages/examples/boilerplate/index.js index 4fa9735bd..d413fc9c5 100644 --- a/packages/examples/boilerplate/index.js +++ b/packages/examples/boilerplate/index.js @@ -5,15 +5,19 @@ import { ethers } from 'ethers'; const signerAlice = ethers.Wallet.createRandom(); // Initialize wallet user, pass 'prod' instead of 'staging' for mainnet apps -const userAlice = await PushAPI.initialize(signerAlice, { env: CONSTANTS.ENV.PROD }); -const userBobAddress = '0x8D4625b4e04d7dE7F158df470a71C5FC4D4d5F4B'; +const userAlice = await PushAPI.initialize(signerAlice, { + env: CONSTANTS.ENV.PROD, +}); +const userBobAddress = '0x60cD05eb31cc16cC37163D514bEF162406d482e1'; const generateRandomWordsWithTimestamp = () => { - return `${Math.random().toString(36).substring(2)} - ${new Date().toISOString()}`; -} + return `${Math.random() + .toString(36) + .substring(2)} - ${new Date().toISOString()}`; +}; userAlice.chat.send(userBobAddress, { content: "Gm gm! It's a me... Alice! - " + generateRandomWordsWithTimestamp(), }); -console.log('Message sent from Alice to ', userBobAddress); \ No newline at end of file +console.log('Message sent from Alice to ', userBobAddress); diff --git a/packages/uiweb/package.json b/packages/uiweb/package.json index 4f5af112d..7aa9bc513 100644 --- a/packages/uiweb/package.json +++ b/packages/uiweb/package.json @@ -37,7 +37,7 @@ "uuid": "^9.0.1" }, "peerDependencies": { - "@pushprotocol/restapi": "1.7.13", + "@pushprotocol/restapi": "1.7.17", "@pushprotocol/socket": "^0.5.0", "react": ">=16.8.0", "styled-components": "^6.0.8" diff --git a/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx b/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx index 0ca99ff1d..0281249b6 100644 --- a/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatProfile/ChatProfile.tsx @@ -38,7 +38,6 @@ import InfoIcon from '../../../icons/infodark.svg'; // Interfaces & Types import useUserInfoUtilities from '../../../hooks/chat/useUserInfoUtilities'; import { Group, IChatProfile } from '../exportedTypes'; -import { ChatInfoResponse } from '../types'; // Constants diff --git a/packages/uiweb/src/lib/components/chat/ChatViewList/ActionRequestBubble.tsx b/packages/uiweb/src/lib/components/chat/ChatViewList/ActionRequestBubble.tsx index 46d5ae188..5f94d9dba 100644 --- a/packages/uiweb/src/lib/components/chat/ChatViewList/ActionRequestBubble.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatViewList/ActionRequestBubble.tsx @@ -10,7 +10,7 @@ import ParticleEffectButton from '../../reusables/ParticleEffectButton'; import { Group } from '../exportedTypes'; import { IChatTheme } from '../theme'; import { ThemeContext } from '../theme/ThemeProvider'; -import { ChatInfoResponse } from '../types'; +import { IChatInfoResponse } from '../types'; import { AcceptCircleIcon, CancelCircleIcon } from '../../../icons/PushIcons'; // Constants @@ -27,7 +27,7 @@ interface IThemeProps { theme?: IChatTheme; } export interface IActionRequestBubbleProps { - chatInfo?: ChatInfoResponse | null; + chatInfo?: IChatInfoResponse | null; } export const ActionRequestBubble = ({ chatInfo = null }: IActionRequestBubbleProps) => { diff --git a/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx b/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx index fad798f75..985d357e3 100644 --- a/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx +++ b/packages/uiweb/src/lib/components/chat/ChatViewList/ChatViewList.tsx @@ -27,7 +27,7 @@ import { ThemeContext } from '../theme/ThemeProvider'; // Interfaces & Types import { Group, IChatViewListProps } from '../exportedTypes'; import { IChatTheme } from '../theme'; -import { ChatInfoResponse } from '../types'; +import { IChatInfoResponse } from '../types'; /** * @interface IThemeProps @@ -40,7 +40,7 @@ interface IThemeProps { interface IChatViewListInitialized { loading: boolean; - chatInfo: ChatInfoResponse | null; + chatInfo: IChatInfoResponse | null; isHidden: boolean; invalidChat: boolean; } @@ -92,31 +92,16 @@ export const ChatViewList: React.FC = (options: IChatViewLis (async () => { if (!user) return; if (chatId) { - const info = await fetchChat({ chatId: chatId }); + const info = await user.chat.info(chatId); console.debug('UIWeb::components::ChatViewList::useEffect::fetchChat', info); // if readmode, then only public true is considered - // TODO: Hack for interface not declared properly (info?.meta as any)?.encryption - // TODO: Hack for interface not declared properly (info?.meta as any)?.groupInfo?.public let hidden = false; if (user && user.readmode()) { - //check if encryption is false, only true for public groups - hidden = !(info?.meta as any)?.groupInfo?.public ?? true; + //check if encrypted is false, only true for public groups + hidden = !info?.meta?.groupInfo?.public ?? true; } else if (user && info?.meta) { - // Only executes when user is not readmode - // if encryption is false, return as is - // covers public group - // TODO: Hack for interface not declared properly (info?.meta as any)?.encryption - if ((info?.meta as any)?.encryption === false) { - hidden = false; - } else if (info?.meta?.group) { - // if encryption is true and group is in user list then hidden is false else true - // if group is encrypted, check if user list is CHATS, encryptioon false takes care of public groups - hidden = info.list === 'CHATS' ? false : true; - } else { - // if it's not a group, then dm is always not hidden - hidden = false; - } - hidden = false; + // visibility is automatically defined + hidden = !info?.meta?.visibility; } else if (!info?.meta) { // TODO: Hack because chat.info doesn't return meta for UNINITIALIZED chats // Assuming this only happens for UNINITIALIZED chats which is a dm @@ -130,7 +115,7 @@ export const ChatViewList: React.FC = (options: IChatViewLis // Finally initialize the component setInitialized({ loading: false, - chatInfo: Object.keys(info || {}).length ? (info as ChatInfoResponse) : null, + chatInfo: Object.keys(info || {}).length ? (info as IChatInfoResponse) : null, isHidden: hidden, invalidChat: info === undefined ? true : false, }); @@ -160,24 +145,26 @@ export const ChatViewList: React.FC = (options: IChatViewLis // Change listtype to 'CHATS' and hidden to false when chatAcceptStream is received useEffect(() => { if (Object.keys(chatAcceptStream || {}).length > 0 && chatAcceptStream.constructor === Object) { - // Check if chat was encrypted, if so, reload the chat - if ((initialized.chatInfo?.meta as any)?.encryption === false) { - setInitialized({ loading: true, chatInfo: null, isHidden: false, invalidChat: false }); - } else { - // If not encrypted, then set hidden to false - const updatedChatInfo = { ...(initialized.chatInfo as ChatInfoResponse) }; - if (updatedChatInfo) updatedChatInfo.list = 'CHATS'; + // Always change hidden to false and list will be CHATS + const updatedChatInfo = { ...(initialized.chatInfo as IChatInfoResponse) }; + if (updatedChatInfo) updatedChatInfo.list = 'CHATS'; + // set initialized after chat accept animation is done + const timer = setTimeout(() => { setInitialized({ ...initialized, chatInfo: updatedChatInfo, isHidden: false }); - } + }, 1000); + + return () => clearTimeout(timer); } + + return () => {}; }, [chatAcceptStream, participantJoinStream]); // Change listtype to 'UINITIALIZED' and hidden to true when participantRemoveStream or participantLeaveStream is received useEffect(() => { if (Object.keys(participantRemoveStream || {}).length > 0 && participantRemoveStream.constructor === Object) { // If not encrypted, then set hidden to false - const updatedChatInfo = { ...(initialized.chatInfo as ChatInfoResponse) }; + const updatedChatInfo = { ...(initialized.chatInfo as IChatInfoResponse) }; if (updatedChatInfo) updatedChatInfo.list = 'UNINITIALIZED'; setInitialized({ ...initialized, chatInfo: updatedChatInfo, isHidden: true }); @@ -334,9 +321,8 @@ export const ChatViewList: React.FC = (options: IChatViewLis /> )} - {/* TODO: Hack for interface not declared properly (initialized.chatInfo?.meta as any)?.encryption */} {!initialized.loading && - ((initialized.chatInfo?.meta as any)?.encryption ? ( + (initialized.chatInfo?.meta?.encrypted ? ( ) : user && user.readmode() ? ( diff --git a/packages/uiweb/src/lib/components/chat/MessageInput/MessageInput.tsx b/packages/uiweb/src/lib/components/chat/MessageInput/MessageInput.tsx index a28cb118e..9aaa33add 100644 --- a/packages/uiweb/src/lib/components/chat/MessageInput/MessageInput.tsx +++ b/packages/uiweb/src/lib/components/chat/MessageInput/MessageInput.tsx @@ -30,7 +30,7 @@ import { MODAL_BACKGROUND_TYPE, MODAL_POSITION_TYPE, type FileMessageContent } f import { GIFType, Group, IChatTheme, MessageInputProps } from '../exportedTypes'; import { checkIfAccessVerifiedGroup } from '../helpers'; import { InfoContainer } from '../reusables'; -import { ChatInfoResponse } from '../types'; +import { IChatInfoResponse } from '../types'; /** * @interface IThemeProps @@ -89,7 +89,7 @@ export const MessageInput: React.FC = ({ const { getGroupByIDnew } = useGetGroupByIDnew(); const [groupInfo, setGroupInfo] = useState(null); - const [chatInfo, setChatInfo] = useState(null); + const [chatInfo, setChatInfo] = useState(null); const theme = useContext(ThemeContext); const isMobile = useDeviceWidthCheck(425); const { sendMessage, loading } = usePushSendMessage(); @@ -162,14 +162,19 @@ export const MessageInput: React.FC = ({ (async () => { if (!user) return; if (chatId) { - let formattedChatId; - if (chatId.includes('.')) { - formattedChatId = (await deriveChatId(chatId, user))!; - } else formattedChatId = chatId; - setFormattedChatId(formattedChatId); - const chat = await fetchChat({ chatId: formattedChatId }); - if (Object.keys(chat || {}).length) { - setChatInfo(chat as ChatInfoResponse); + let derivedChatId = chatId; + if (derivedChatId.includes('.')) { + derivedChatId = (await deriveChatId(chatId, user))!; + } + + // set formatted chat id + setFormattedChatId(derivedChatId); + + try { + const chat = await user.chat.info(derivedChatId); + setChatInfo(chat); + } catch (error) { + console.error('UIWeb::MessageInput::useEffect[chatId, user]::error while fetching chat info', error); } } })(); @@ -236,7 +241,8 @@ export const MessageInput: React.FC = ({ chatId: prevInfo.chatId, // Directly use the existing chatId, ensuring it's not undefined meta: { group: prevInfo.meta?.group ?? false, // Provide default value if undefined - encryption: prevInfo.meta?.encryption ?? false, + encrypted: prevInfo.meta?.encrypted ?? false, + visibility: prevInfo.meta?.visibility ?? true, }, }; }); diff --git a/packages/uiweb/src/lib/components/chat/types/index.ts b/packages/uiweb/src/lib/components/chat/types/index.ts index 3cf8c0b47..bee046a06 100644 --- a/packages/uiweb/src/lib/components/chat/types/index.ts +++ b/packages/uiweb/src/lib/components/chat/types/index.ts @@ -96,17 +96,19 @@ export const CRITERIA_TYPE = { export type CriteriaType = keyof typeof CRITERIA_TYPE; -export interface ChatInfoResponse { +export interface IChatInfoResponse { chatId: string; - meta: { + list: string; + meta?: { + encrypted: boolean; + visibility: boolean; group: boolean; - encryption: boolean; groupInfo?: { public: boolean; }; + recipents?: string[]; }; participants?: Array; recipient?: string; - list: string; } export * from './tokenGatedGroupCreationType'; diff --git a/packages/uiweb/yarn.lock b/packages/uiweb/yarn.lock index 023594731..733887673 100644 --- a/packages/uiweb/yarn.lock +++ b/packages/uiweb/yarn.lock @@ -1810,7 +1810,7 @@ __metadata: react-twitter-embed: "npm:^4.0.4" uuid: "npm:^9.0.1" peerDependencies: - "@pushprotocol/restapi": 1.7.13 + "@pushprotocol/restapi": 1.7.17 "@pushprotocol/socket": ^0.5.0 react: ">=16.8.0" styled-components: ^6.0.8