diff --git a/src/components/ConversationListItem.tsx b/src/components/ConversationListItem.tsx index f876e69..2187c20 100644 --- a/src/components/ConversationListItem.tsx +++ b/src/components/ConversationListItem.tsx @@ -15,6 +15,11 @@ interface ConversationListItemProps { lastMessageTime: number; } +/** + * + * @deprecated only leaving v3 for now + * + */ export const ConversationListItem: FC = ({ conversation, display, @@ -26,8 +31,8 @@ export const ConversationListItem: FC = ({ return ( { - navigate(ScreenNames.Conversation, { - topic: conversation.topic, + navigate(ScreenNames.Group, { + id: conversation.topic, }); }}> diff --git a/src/hooks/useListMessages.ts b/src/hooks/useListMessages.ts index ee5bd90..41e4837 100644 --- a/src/hooks/useListMessages.ts +++ b/src/hooks/useListMessages.ts @@ -1,13 +1,6 @@ import {useQueryClient} from '@tanstack/react-query'; import {useEffect} from 'react'; -import {DeviceEventEmitter} from 'react-native'; -import {ContentTypes} from '../consts/ContentTypes'; -import {EventEmitterEvents} from '../consts/EventEmitters'; -import { - ListConversation, - ListGroup, - ListMessages, -} from '../models/ListMessages'; +import {ListMessages} from '../models/ListMessages'; import {QueryKeys} from '../queries/QueryKeys'; import {useListQuery} from '../queries/useListQuery'; import {useClient} from './useClient'; @@ -16,127 +9,34 @@ export const useListMessages = () => { const {client} = useClient(); const queryClient = useQueryClient(); - useEffect(() => { - const startStream = () => { - if (!client) { - return; - } - client.conversations.streamAllMessages(async message => { - const topic = message.topic; - const content = message.content(); - const messageStringContent = - typeof content === 'string' ? content : message.fallback ?? ''; - queryClient.setQueryData( - [QueryKeys.List, client?.address], - prev => { - const existingConversation = prev?.find(it => { - return 'conversation' in it && it.conversation.topic === topic; - }); - // Handle existing conversations here, new conversations handled in stream - if (existingConversation) { - const data = prev?.map(it => { - if ('conversation' in it && it.conversation.topic === topic) { - if ('conversation' in existingConversation) { - const newIt: ListConversation = { - conversation: existingConversation.conversation, - display: messageStringContent, - lastMessageTime: message.sent, - isRequest: it.isRequest, - }; - return newIt; - } - } - return it; - }); - return data; - } else { - const existingGroup = prev?.find(it => { - return 'group' in it && it.group.id === topic; - }); - if (existingGroup) { - if ( - message.contentTypeId === ContentTypes.GroupMembershipChange - ) { - DeviceEventEmitter.emit( - `${EventEmitterEvents.GROUP_CHANGED}_${topic}`, - ); - } - const data = prev?.map(it => { - if ('group' in it && it.group.id === topic) { - if ('group' in existingGroup) { - const newIt: ListGroup = { - group: existingGroup.group, - display: messageStringContent, - lastMessageTime: message.sent, - isRequest: it.isRequest, - }; - return newIt; - } - } - return it; - }); - return data; - } else { - return prev; - } - } - }, - ); - }); - }; - - startStream(); - - return () => { - client?.conversations.cancelStreamAllMessages(); - }; - }, [client, queryClient]); - - useEffect(() => { - const startStream = () => { - if (!client) { - return; - } - client.conversations.stream(async newConversation => { - const [consent] = await Promise.all([newConversation.consentState()]); - const content = ''; - queryClient.setQueryData( - [QueryKeys.List, client?.address], - prev => { - return [ - { - conversation: newConversation, - display: content, - lastMessageTime: Date.now(), - isRequest: consent !== 'allowed', - }, - ...(prev ?? []), - ]; - }, - ); - }); - }; - - startStream(); - - return () => { - client?.conversations.cancelStream(); - }; - }, [client, queryClient]); - useEffect(() => { const startStream = () => { if (!client) { return; } client.conversations.streamGroups(async newGroup => { + let content = ''; + try { + const groupMessages = await newGroup.messages(); + try { + const lastMessageContent = groupMessages[0]?.content(); + content = + typeof lastMessageContent === 'string' + ? lastMessageContent + : groupMessages[0]?.fallback ?? ''; + } catch (err) { + content = groupMessages[0]?.fallback ?? ''; + } + } catch (err) { + content = ''; + } queryClient.setQueryData( [QueryKeys.List, client?.address], prev => { return [ { group: newGroup, - display: '', + display: content, lastMessageTime: Date.now(), isRequest: false, }, diff --git a/src/models/ListMessages.ts b/src/models/ListMessages.ts index 8994e79..717a5fa 100644 --- a/src/models/ListMessages.ts +++ b/src/models/ListMessages.ts @@ -7,6 +7,9 @@ export interface ListItem { isRequest: boolean; } +/** + * @deprecated only leaving v3 for now + */ export interface ListConversation extends ListItem { conversation: Conversation; } @@ -15,4 +18,4 @@ export interface ListGroup extends ListItem { group: Group; } -export type ListMessages = (ListConversation | ListGroup)[]; +export type ListMessages = ListGroup[]; diff --git a/src/navigation/AppNavigation.tsx b/src/navigation/AppNavigation.tsx index 15a2d24..beb1c8f 100644 --- a/src/navigation/AppNavigation.tsx +++ b/src/navigation/AppNavigation.tsx @@ -5,7 +5,6 @@ import {Platform} from 'react-native'; import {useClientContext} from '../context/ClientContext'; import {AccountSettingsScreen} from '../screens/AccountSettingsScreen'; import {ConversationListScreen} from '../screens/ConversationListScreen'; -import {ConversationScreen} from '../screens/ConversationScreen'; import {DevScreen} from '../screens/DevScreen'; import {GroupScreen} from '../screens/GroupScreen'; import {LoadingScreen} from '../screens/LoadingScreen'; @@ -79,10 +78,6 @@ export const AppNavigation = () => { name={ScreenNames.ConversationList} component={ConversationListScreen} /> - = { [ScreenNames.OnboardingEnableIdentity]: 'onboarding_enable_identity', [ScreenNames.Account]: 'account', [ScreenNames.ConversationList]: 'conversation_list', - [ScreenNames.Conversation]: 'conversation/:topic', [ScreenNames.NewConversation]: { path: 'new_conversation/:addresses', parse: { diff --git a/src/screens/ConversationListScreen.tsx b/src/screens/ConversationListScreen.tsx index c787eee..189cb75 100644 --- a/src/screens/ConversationListScreen.tsx +++ b/src/screens/ConversationListScreen.tsx @@ -4,7 +4,6 @@ import {Box, Center, Fab, FlatList, HStack, VStack} from 'native-base'; import React, {FC, useCallback, useMemo, useState} from 'react'; import {ListRenderItem, Pressable} from 'react-native'; import {AvatarWithFallback} from '../components/AvatarWithFallback'; -import {ConversationListItem} from '../components/ConversationListItem'; import {GroupListItem} from '../components/GroupListItem'; import {Button} from '../components/common/Button'; import {Drawer} from '../components/common/Drawer'; @@ -16,18 +15,13 @@ import {useClient} from '../hooks/useClient'; import {useListMessages} from '../hooks/useListMessages'; import {useTypedNavigation} from '../hooks/useTypedNavigation'; import {translate} from '../i18n'; -import { - ListConversation, - ListGroup, - ListMessages, -} from '../models/ListMessages'; +import {ListGroup, ListMessages} from '../models/ListMessages'; import {ScreenNames} from '../navigation/ScreenNames'; import {colors} from '../theme/colors'; const EmptyBackground = require('../../assets/images/Bg_asset.svg').default; -const keyExtractor = (item: ListConversation | ListGroup) => - 'conversation' in item ? item.conversation?.topic : item.group?.id ?? ''; +const keyExtractor = (item: ListGroup) => item.group?.id ?? ''; const useData = () => { const {client} = useClient(); @@ -219,27 +213,15 @@ export const ConversationListScreen = () => { [], ); - const renderItem: ListRenderItem = useCallback( - ({item}) => { - if ('conversation' in item) { - return ( - - ); - } - return ( - - ); - }, - [], - ); + const renderItem: ListRenderItem = useCallback(({item}) => { + return ( + + ); + }, []); return ( <> diff --git a/src/screens/ConversationScreen.tsx b/src/screens/ConversationScreen.tsx index 0a86213..7ad38e0 100644 --- a/src/screens/ConversationScreen.tsx +++ b/src/screens/ConversationScreen.tsx @@ -89,6 +89,11 @@ const getInitialConsentState = (address: string, peerAddress: string) => { return 'denied'; }; +/** + * + * @deprecated This screen is not used anymore + * keeping it for reference in case we want UI of 1 to 1 chats to be different + */ export const ConversationScreen = () => { const {params} = useRoute(); const {topic} = params as {topic: string}; diff --git a/src/screens/NewConversationScreen.tsx b/src/screens/NewConversationScreen.tsx index 9d21953..37547a9 100644 --- a/src/screens/NewConversationScreen.tsx +++ b/src/screens/NewConversationScreen.tsx @@ -13,7 +13,6 @@ import {useTypedNavigation} from '../hooks/useTypedNavigation'; import {ListMessages} from '../models/ListMessages'; import {ScreenNames} from '../navigation/ScreenNames'; import {QueryKeys} from '../queries/QueryKeys'; -import {mmkvStorage} from '../services/mmkvStorage'; export const NewConversationScreen = () => { const {replace} = useTypedNavigation(); @@ -25,55 +24,40 @@ export const NewConversationScreen = () => { const onSend = useCallback( async (message: {text?: string; asset?: Asset}) => { // TODO: Error Handling - if (addresses.length !== 1) { - const canMessage = await client?.canGroupMessage(addresses); - if (!canMessage && Platform.OS === 'android') { - Alert.alert('You do not have permission to message this group'); - return; - } - client?.conversations - ?.newGroup(addresses) - .then(group => { - // The client is not notified of a group they create, so we add it to the list here - group - .send(message as {text: string}) - .then(() => { - queryClient.setQueryData( - [QueryKeys.List, client?.address], - prev => { - return [ - { - group, - display: message.text ?? 'Image', - lastMessageTime: Date.now(), - isRequest: false, - }, - ...(prev ?? []), - ]; - }, - ); - }) - .finally(() => { - replace(ScreenNames.Group, {id: group.id}); - }); - }) - .catch(err => { - console.log('error on new', err); - }); - } else { - const canMessage = await client?.canMessage(addresses[0]); - if (!canMessage) { - Alert.alert('You do not have permission to message this group'); - return; - } - client?.conversations - ?.newConversation(addresses[0]) - .then(conversation => { - mmkvStorage.saveConsent(client?.address, addresses[0], true); - conversation.send(message as {text: string}); - replace(ScreenNames.Conversation, {topic: conversation.topic}); - }); + const canMessage = await client?.canGroupMessage(addresses); + if (!canMessage && Platform.OS === 'android') { + Alert.alert('You do not have permission to message this group'); + return; } + client?.conversations + ?.newGroup(addresses) + .then(group => { + // The client is not notified of a group they create, so we add it to the list here + group + .send(message as {text: string}) + .then(() => { + queryClient.setQueryData( + [QueryKeys.List, client?.address], + prev => { + return [ + { + group, + display: message.text ?? 'Image', + lastMessageTime: Date.now(), + isRequest: false, + }, + ...(prev ?? []), + ]; + }, + ); + }) + .finally(() => { + replace(ScreenNames.Group, {id: group.id}); + }); + }) + .catch(err => { + console.log('error on new', err); + }); }, [addresses, client, queryClient, replace], ); diff --git a/src/utils/getAllListMessages.ts b/src/utils/getAllListMessages.ts index e2c16c8..a19e97f 100644 --- a/src/utils/getAllListMessages.ts +++ b/src/utils/getAllListMessages.ts @@ -1,9 +1,5 @@ import {Client} from '@xmtp/react-native-sdk'; -import { - ListConversation, - ListGroup, - ListMessages, -} from '../models/ListMessages'; +import {ListGroup, ListMessages} from '../models/ListMessages'; import {mmkvStorage} from '../services/mmkvStorage'; import {withRequestLogger} from './logger'; @@ -29,34 +25,13 @@ export const getAllListMessages = async (client?: Client | null) => { ); }); - const [convos, groups] = await Promise.all([ - withRequestLogger(client.conversations.list(), {name: 'list'}), - withRequestLogger(client.conversations.listGroups(), {name: 'groups'}), - ]); + const groups = await withRequestLogger(client.conversations.listGroups(), { + name: 'groups', + }); - const allMessages: PromiseSettledResult[] = - await Promise.allSettled([ - ...convos.map(async conversation => { - const [messages, consent] = await Promise.all([ - withRequestLogger(conversation.messages(1), { - name: 'conversation_messages', - }), - withRequestLogger(conversation.consentState(), { - name: 'conversation_consent', - }), - ]); - const content = messages?.[0]?.content(); - return { - conversation, - display: - typeof content === 'string' - ? content - : messages[0].fallback ?? '', - lastMessageTime: messages[0].sent, - isRequest: consent !== 'allowed', - }; - }), - ...groups.map(async group => { + const allMessages: PromiseSettledResult[] = + await Promise.allSettled( + groups.map(async group => { await group.sync(); const messages = await withRequestLogger(group.messages(), { name: 'group_messages', @@ -73,7 +48,7 @@ export const getAllListMessages = async (client?: Client | null) => { isRequest: false, }; }), - ]); + ); // Remove the rejected promises and return the list of messages using .reduce const allMessagesFiltered = allMessages.reduce(