diff --git a/example/App.tsx b/example/App.tsx index fa7d87dd0..f475f8792 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -1,7 +1,7 @@ import { NavigationContainer } from '@react-navigation/native' +import React from 'react' import { Button, Platform } from 'react-native' import { QueryClient, QueryClientProvider } from 'react-query' -import { XmtpProvider } from 'xmtp-react-native-sdk' import ConversationCreateScreen from './src/ConversationCreateScreen' import ConversationScreen from './src/ConversationScreen' @@ -9,12 +9,13 @@ import HomeScreen from './src/HomeScreen' import LaunchScreen from './src/LaunchScreen' import { Navigator } from './src/Navigation' import TestScreen from './src/TestScreen' +import { XmtpContextProvider } from './src/XmtpContext' const queryClient = new QueryClient() export default function App() { return ( - + - + ) } diff --git a/example/src/ConversationCreateScreen.tsx b/example/src/ConversationCreateScreen.tsx index 9f0676dc9..f2a80d984 100644 --- a/example/src/ConversationCreateScreen.tsx +++ b/example/src/ConversationCreateScreen.tsx @@ -1,9 +1,9 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack' import React, { useState } from 'react' import { Button, ScrollView, Text, TextInput } from 'react-native' -import { useXmtp } from 'xmtp-react-native-sdk' import { NavigationParamList } from './Navigation' +import { useXmtp } from './XmtpContext' export default function ConversationCreateScreen({ route, diff --git a/example/src/ConversationScreen.tsx b/example/src/ConversationScreen.tsx index 5b12e2b4b..b6e92a649 100644 --- a/example/src/ConversationScreen.tsx +++ b/example/src/ConversationScreen.tsx @@ -8,7 +8,7 @@ import * as ImagePicker from 'expo-image-picker' import type { ImagePickerAsset } from 'expo-image-picker' import { PermissionStatus } from 'expo-modules-core' import moment from 'moment' -import React, { useCallback, useMemo, useRef, useState } from 'react' +import React, { useRef, useState } from 'react' import { Button, FlatList, @@ -30,10 +30,11 @@ import { DecodedMessage, StaticAttachmentContent, ReplyContent, - useClient, + Client, } from 'xmtp-react-native-sdk' import { NavigationParamList } from './Navigation' +import { useXmtp } from './XmtpContext' import { useConversation, useMessage, @@ -56,7 +57,7 @@ export default function ConversationScreen({ }: NativeStackScreenProps) { const { topic } = route.params const messageListRef = useRef(null) - const { + let { data: messages, refetch: refreshMessages, isFetching, @@ -73,15 +74,10 @@ export default function ConversationScreen({ fileUri: attachment?.image?.uri || attachment?.file?.uri, mimeType: attachment?.file?.mimeType, }) - - const filteredMessages = useMemo( - () => - (messages ?? [])?.filter( - (message) => !hiddenMessageTypes.includes(message.contentTypeId) - ), - [messages] + messages = (messages || []).filter( + (message) => !hiddenMessageTypes.includes(message.contentTypeId) ) - + // console.log("messages", JSON.stringify(messages, null, 2)); const sendMessage = async (content: any) => { setSending(true) console.log('Sending message', content) @@ -106,22 +102,16 @@ export default function ConversationScreen({ const sendRemoteAttachmentMessage = () => sendMessage({ remoteAttachment }).then(() => setAttachment(null)) const sendTextMessage = () => sendMessage({ text }).then(() => setText('')) - const scrollToMessageId = useCallback( - (messageId: string) => { - const index = (filteredMessages || []).findIndex( - (m) => m.id === messageId - ) - if (index === -1) { - return - } - return messageListRef.current?.scrollToIndex({ - index, - animated: true, - }) - }, - [filteredMessages] - ) - + const scrollToMessageId = (messageId: string) => { + const index = (messages || []).findIndex((m) => m.id === messageId) + if (index === -1) { + return + } + return messageListRef.current?.scrollToIndex({ + index, + animated: true, + }) + } return ( message.id} @@ -164,9 +154,9 @@ export default function ConversationScreen({ onReply={() => setReplyingTo(message.id)} onMessageReferencePress={scrollToMessageId} showSender={ - index === (filteredMessages || []).length - 1 || - (index + 1 < (filteredMessages || []).length && - filteredMessages![index + 1].senderAddress !== + index === (messages || []).length - 1 || + (index + 1 < (messages || []).length && + messages![index + 1].senderAddress !== message.senderAddress) } /> @@ -1056,7 +1046,7 @@ function MessageContents({ contentTypeId: string content: any }) { - const { client } = useClient() + const { client }: { client: Client } = useXmtp() if (contentTypeId === 'xmtp.org/text:1.0') { const text: string = content @@ -1090,8 +1080,8 @@ function MessageContents({ if (contentTypeId === 'xmtp.org/reply:1.0') { const replyContent: ReplyContent = content const replyContentType = replyContent.contentType - const codec = client?.codecRegistry[replyContentType] - const actualReplyContent = codec?.decode(replyContent.content) + const codec = client.codecRegistry[replyContentType] + const actualReplyContent = codec.decode(replyContent.content) return ( diff --git a/example/src/HomeScreen.tsx b/example/src/HomeScreen.tsx index f137b2d55..fe19e122a 100644 --- a/example/src/HomeScreen.tsx +++ b/example/src/HomeScreen.tsx @@ -9,8 +9,9 @@ import { Text, View, } from 'react-native' -import { Conversation, Client, useXmtp } from 'xmtp-react-native-sdk' +import { Conversation, Client } from 'xmtp-react-native-sdk' +import { useXmtp } from './XmtpContext' import { useConversationList, useMessages } from './hooks' /// Show the user's list of conversations. diff --git a/example/src/LaunchScreen.tsx b/example/src/LaunchScreen.tsx index ed889fc29..191666314 100644 --- a/example/src/LaunchScreen.tsx +++ b/example/src/LaunchScreen.tsx @@ -1,10 +1,10 @@ import { NativeStackScreenProps } from '@react-navigation/native-stack' -import React, { useCallback } from 'react' +import React from 'react' import { Button, ScrollView, StyleSheet, Text, View } from 'react-native' import * as XMTP from 'xmtp-react-native-sdk' -import { useXmtp } from 'xmtp-react-native-sdk' import { NavigationParamList } from './Navigation' +import { useXmtp } from './XmtpContext' import { useSavedKeys } from './hooks' const appVersion = 'XMTP_RN_EX/0.0.1' @@ -22,26 +22,24 @@ export default function LaunchScreen({ }: NativeStackScreenProps) { const { setClient } = useXmtp() const savedKeys = useSavedKeys() - const configureWallet = useCallback( - (label: string, configuring: Promise) => { - console.log('Connecting XMTP client', label) - configuring - .then(async (client) => { - console.log('Connected XMTP client', label, { - address: client.address, - }) - setClient(client) - navigation.navigate('home') - // Save the configured client keys for use in later sessions. - const keyBundle = await client.exportKeyBundle() - await savedKeys.save(keyBundle) + const configureWallet = ( + label: string, + configuring: Promise + ) => { + console.log('Connecting XMTP client', label) + configuring + .then(async (client) => { + console.log('Connected XMTP client', label, { + address: client.address, }) - .catch((err) => - console.log('Unable to connect XMTP client', label, err) - ) - }, - [] - ) + setClient(client) + navigation.navigate('home') + // Save the configured client keys for use in later sessions. + const keyBundle = await client.exportKeyBundle() + await savedKeys.save(keyBundle) + }) + .catch((err) => console.log('Unable to connect XMTP client', label, err)) + } return ( void +}>({ + client: null, + setClient: () => {}, +}) +export const useXmtp = () => useContext(XmtpContext) +type Props = { + children: ReactNode +} +export const XmtpContextProvider: FC = ({ children }) => { + const [client, setClient] = useState(null) + const context = useMemo(() => ({ client, setClient }), [client, setClient]) + return {children} +} diff --git a/example/src/hooks.tsx b/example/src/hooks.tsx index dc64123b2..ea34a2777 100644 --- a/example/src/hooks.tsx +++ b/example/src/hooks.tsx @@ -7,9 +7,9 @@ import { EncryptedLocalAttachment, ReactionContent, RemoteAttachmentContent, - useXmtp, } from 'xmtp-react-native-sdk' +import { useXmtp } from './XmtpContext' import { downloadFile, uploadFile } from './storage' /** diff --git a/src/index.ts b/src/index.ts index 3005ea791..93ab5d90f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -344,18 +344,12 @@ export async function isDenied( return await XMTPModule.isDenied(clientAddress, address) } -export async function denyContacts( - clientAddress: string, - addresses: string[] -): Promise { - return await XMTPModule.denyContacts(clientAddress, addresses) +export function denyContacts(clientAddress: string, addresses: string[]) { + XMTPModule.denyContacts(clientAddress, addresses) } -export async function allowContacts( - clientAddress: string, - addresses: string[] -): Promise { - return await XMTPModule.allowContacts(clientAddress, addresses) +export function allowContacts(clientAddress: string, addresses: string[]) { + XMTPModule.allowContacts(clientAddress, addresses) } export async function refreshConsentList( diff --git a/src/lib/Contacts.ts b/src/lib/Contacts.ts index 3ea970f9f..4738fc6d7 100644 --- a/src/lib/Contacts.ts +++ b/src/lib/Contacts.ts @@ -17,12 +17,12 @@ export default class Contacts { return await XMTPModule.isDenied(this.client.address, address) } - async deny(addresses: string[]): Promise { - return await XMTPModule.denyContacts(this.client.address, addresses) + deny(addresses: string[]) { + XMTPModule.denyContacts(this.client.address, addresses) } - async allow(addresses: string[]): Promise { - return await XMTPModule.allowContacts(this.client.address, addresses) + allow(addresses: string[]) { + XMTPModule.allowContacts(this.client.address, addresses) } async refreshConsentList(): Promise {