Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates: #37

Merged
merged 2 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ PODS:
- GzipSwift
- LibXMTP (= 0.4.1-beta2)
- web3.swift
- XMTPReactNative (1.27.0-beta.6):
- XMTPReactNative (1.27.0-beta.8):
- ExpoModulesCore
- MessagePacker
- secp256k1.swift
Expand Down Expand Up @@ -1636,7 +1636,7 @@ SPEC CHECKSUMS:
WatermelonDB: 842d22ba555425aa9f3ce551239a001200c539bc
web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959
XMTP: b70e7b864e38d430d2b55e813f33eec775ed0f0d
XMTPReactNative: ca17e3be61be4744a89182c372228c4a776a4693
XMTPReactNative: 2b9f6fce13a1cda76d600edc76bb7967fdef845f
Yoga: e64aa65de36c0832d04e8c7bd614396c77a80047

PODFILE CHECKSUM: c765268d8eab018a5f4619e1d00ca4dab437bc4f
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@tanstack/react-query": "^5.17.19",
"@thirdweb-dev/react-native": "^0.5.4",
"@thirdweb-dev/react-native-compat": "^0.5.4",
"@xmtp/react-native-sdk": "1.27.0-beta.6",
"@xmtp/react-native-sdk": "1.27.0-beta.8",
"aws-sdk": "^2.1540.0",
"ethers": "^5",
"expo": ">=50.0.0-0 <51.0.0",
Expand Down
5 changes: 4 additions & 1 deletion src/components/Blockie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ function createImageData(size: number): number[] {

export const Blockie: FC<BlockieProps> = ({address, size: propSize}) => {
const {size, scale, bgcolor, color, spotcolor} = useMemo(() => {
return buildBlockieOpts({seed: address, size: propSize});
return buildBlockieOpts({
seed: address.toLocaleLowerCase(),
size: propSize,
});
}, [address, propSize]);

const imageData = useMemo(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ConversationMessageContent.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {DecodedMessage, RemoteAttachmentContent} from '@xmtp/react-native-sdk';
import {Container} from 'native-base';
import React, {FC} from 'react';
import {ContentTypes} from '../consts/ContentTypes';
import {ContentTypes, SupportedContentTypes} from '../consts/ContentTypes';
import {translate} from '../i18n';
import {colors} from '../theme/colors';
import {ImageMessage} from './ImageMessage';
import {Text} from './common/Text';

interface ConversationMessageContentProps {
message: DecodedMessage<unknown>;
message: DecodedMessage<SupportedContentTypes>;
isMe: boolean;
}

Expand Down
38 changes: 25 additions & 13 deletions src/components/GroupAvatarStack.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
import {Box, HStack} from 'native-base';
import React, {FC} from 'react';
import {StyleSheet, ViewStyle} from 'react-native';
import {useContactInfo} from '../hooks/useContactInfo';
import {AvatarWithFallback} from './AvatarWithFallback';

interface GroupAvatarStackProps {
data: {
avatarUrl: string | null;
address: string;
}[];
addresses: string[];
style?: ViewStyle;
}

export const GroupAvatarStack: FC<GroupAvatarStackProps> = ({data, style}) => {
const AvatarWithLoader = ({address}: {address: string}) => {
const {avatarUrl, loading} = useContactInfo(address);
if (loading) {
return (
<AvatarWithFallback address={address} size={32} style={styles.avatar} />
);
}
return (
<AvatarWithFallback
style={styles.avatar}
address={address}
avatarUri={avatarUrl}
size={32}
/>
);
};

export const GroupAvatarStack: FC<GroupAvatarStackProps> = ({
addresses,
style,
}) => {
return (
<Box style={style}>
<HStack maxW={'20px'}>
{data.slice(0, 4).map(({avatarUrl, address}) => (
<AvatarWithFallback
key={address}
size={32}
address={address}
avatarUri={avatarUrl}
style={styles.avatar}
/>
{addresses.slice(0, 4).map(address => (
<AvatarWithLoader key={address} address={address} />
))}
</HStack>
</Box>
Expand Down
9 changes: 6 additions & 3 deletions src/components/GroupHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import {Box, HStack, VStack} from 'native-base';
import React, {FC, PropsWithChildren} from 'react';
import {Platform, Pressable, StyleSheet} from 'react-native';
import {useGroupContactInfo} from '../hooks/useGroupContactInfo';
import {useGroupName} from '../hooks/useGroupName';
import {useTypedNavigation} from '../hooks/useTypedNavigation';
import {colors} from '../theme/colors';
import {GroupAvatarStack} from './GroupAvatarStack';
Expand Down Expand Up @@ -34,7 +34,7 @@
onGroupPress,
}) => {
const {goBack} = useTypedNavigation();
const {data, groupDisplayName} = useGroupContactInfo(peerAddresses);
const groupDisplayName = useGroupName(peerAddresses);

return (
<HeaderContainer>
Expand All @@ -61,7 +61,10 @@
</HStack> */}
</VStack>
<Pressable onPress={onGroupPress}>
<GroupAvatarStack style={{paddingRight: 30}} data={data} />
<GroupAvatarStack
style={{paddingRight: 30}}

Check warning on line 65 in src/components/GroupHeader.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { paddingRight: 30 }
addresses={peerAddresses}
/>
</Pressable>
</HStack>
</HeaderContainer>
Expand Down
14 changes: 9 additions & 5 deletions src/components/GroupListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import {Box, HStack, VStack} from 'native-base';
import React, {FC} from 'react';
import {Pressable} from 'react-native';
import {useGroupContactInfo} from '../hooks/useGroupContactInfo';
import {SupportedContentTypes} from '../consts/ContentTypes';
import {useGroupName} from '../hooks/useGroupName';
import {useTypedNavigation} from '../hooks/useTypedNavigation';
import {ScreenNames} from '../navigation/ScreenNames';
import {useGroupParticipantsQuery} from '../queries/useGroupParticipantsQuery';
Expand All @@ -11,7 +12,7 @@
import {Text} from './common/Text';

interface GroupListItemProps {
group: Group<any>;
group: Group<SupportedContentTypes>;
display: string;
lastMessageTime: number;
}
Expand All @@ -23,7 +24,7 @@
}) => {
const {data: addresses} = useGroupParticipantsQuery(group?.id);
const {navigate} = useTypedNavigation();
const {data, groupDisplayName} = useGroupContactInfo(addresses ?? []);
const groupName = useGroupName(addresses ?? []);

return (
<Pressable
Expand All @@ -34,14 +35,17 @@
}}>
<HStack space={[2, 3]} alignItems={'center'} w={'100%'} padding={'16px'}>
<Box marginRight={'30px'}>
<GroupAvatarStack style={{paddingRight: 10}} data={data} />
<GroupAvatarStack
style={{paddingRight: 10}}

Check warning on line 39 in src/components/GroupListItem.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { paddingRight: 10 }
addresses={addresses ?? []}
/>
</Box>
<VStack flex={1} justifyContent={'flex-end'}>
<Text
numberOfLines={1}
ellipsizeMode="tail"
typography="text-base/bold">
{groupDisplayName}
{groupName}
</Text>
<Text numberOfLines={1} typography="text-sm/regular">
{display}
Expand All @@ -50,7 +54,7 @@
<Text
alignSelf={'flex-start'}
typography="text-xs/regular"
style={{textAlignVertical: 'top'}}>

Check warning on line 57 in src/components/GroupListItem.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { textAlignVertical: 'top' }
{getMessageTimeDisplay(lastMessageTime)}
</Text>
</HStack>
Expand Down
8 changes: 7 additions & 1 deletion src/components/modals/AddGroupParticipantModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import {Group} from '@xmtp/react-native-sdk/build/lib/Group';
import {Box, FlatList, HStack, Input, Pressable, VStack} from 'native-base';
import React, {FC, useCallback, useMemo, useState} from 'react';
import {ListRenderItem, useWindowDimensions} from 'react-native';
import {
DeviceEventEmitter,
ListRenderItem,
useWindowDimensions,
} from 'react-native';
import {EventEmitterEvents} from '../../consts/EventEmitters';
import {TestIds} from '../../consts/TestIds';
import {useContactInfo} from '../../hooks/useContactInfo';
import {useContacts} from '../../hooks/useContacts';
Expand Down Expand Up @@ -69,6 +74,7 @@ export const AddGroupParticipantModal: FC<GroupInfoModalProps> = ({

const onAdd = useCallback(async () => {
await group.addMembers(participants);
DeviceEventEmitter.emit(`${EventEmitterEvents.GROUP_CHANGED}_${group.id}`);
hide();
}, [participants, group, hide]);

Expand Down
5 changes: 5 additions & 0 deletions src/components/modals/GroupInfoModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {Group} from '@xmtp/react-native-sdk/build/lib/Group';
import {HStack, Pressable, VStack} from 'native-base';
import React, {FC, useCallback} from 'react';
import {DeviceEventEmitter} from 'react-native';
import {AppConfig} from '../../consts/AppConfig';
import {EventEmitterEvents} from '../../consts/EventEmitters';
import {useContactInfo} from '../../hooks/useContactInfo';
import {translate} from '../../i18n';
import {colors} from '../../theme/colors';
Expand Down Expand Up @@ -34,7 +36,7 @@
{displayName}
</Text>
<AvatarWithFallback
style={{marginLeft: 10}}

Check warning on line 39 in src/components/modals/GroupInfoModal.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { marginLeft: 10 }
size={40}
address={address}
avatarUri={avatarUrl}
Expand Down Expand Up @@ -78,6 +80,9 @@
const onRemovePress = useCallback(
async (address: string) => {
await group.removeMembers([address]);
DeviceEventEmitter.emit(
`${EventEmitterEvents.GROUP_CHANGED}_${group.id}`,
);
hide();
},
[group, hide],
Expand Down
40 changes: 40 additions & 0 deletions src/consts/ContentTypes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
import {
ContentTypeId,
NativeContentCodec,
NativeMessageContent,
RemoteAttachmentCodec,
} from '@xmtp/react-native-sdk';

type GroupChangeContent = unknown;

class GroupChangeCodec implements NativeContentCodec<GroupChangeContent> {
contentKey: 'groupChange' = 'groupChange';
contentType: ContentTypeId = {
authorityId: 'xmtp.org',
typeId: 'group_membership_change',
versionMajor: 1,
versionMinor: 0,
};

encode(): NativeMessageContent {
return {
// remoteAttachment: content,
};
}

decode(nativeContent: NativeMessageContent): GroupChangeContent {
return nativeContent.text!;
}

fallback(): string | undefined {
return 'This app doesn’t support attachments.';
}
}

export const ContentTypes = {
Text: 'xmtp.org/text:1.0',
RemoteStaticAttachment: 'xmtp.org/remoteStaticAttachment:1.0',
GroupMembershipChange: 'xmtp.org/group_membership_change:1.0',
};

export const supportedContentTypes = [
new RemoteAttachmentCodec(),
new GroupChangeCodec(),
];

export type SupportedContentTypes = typeof supportedContentTypes;
3 changes: 3 additions & 0 deletions src/consts/EventEmitters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export enum EventEmitterEvents {
CREATE_IDENTITY = 'CREATE_IDENTITY',
ENABLE_IDENTITY = 'ENABLE_IDENTITY',

// Group Participants
GROUP_CHANGED = 'GROUP_CHANGED',
}
22 changes: 15 additions & 7 deletions src/context/ClientContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useAddress, useConnectionStatus} from '@thirdweb-dev/react-native';
import {Client, RemoteAttachmentCodec} from '@xmtp/react-native-sdk';
import {Client} from '@xmtp/react-native-sdk';
import React, {
FC,
PropsWithChildren,
Expand All @@ -8,11 +8,17 @@ import React, {
useState,
} from 'react';
import {AppConfig} from '../consts/AppConfig';
import {
SupportedContentTypes,
supportedContentTypes,
} from '../consts/ContentTypes';
import {clearClientKeys, getClientKeys} from '../services/encryptedStorage';

interface ClientContextValue {
client: Client<unknown> | null;
setClient: React.Dispatch<React.SetStateAction<Client<unknown> | null>>;
client: Client<SupportedContentTypes> | null;
setClient: React.Dispatch<
React.SetStateAction<Client<SupportedContentTypes> | null>
>;
loading: boolean;
}

Expand All @@ -25,7 +31,9 @@ export const ClientContext = createContext<ClientContextValue>({
});

export const ClientProvider: FC<PropsWithChildren> = ({children}) => {
const [client, setClient] = useState<Client<unknown> | null>(null);
const [client, setClient] = useState<Client<SupportedContentTypes> | null>(
null,
);
const [loading, setLoading] = useState(true);
const address = useAddress();
const status = useConnectionStatus();
Expand All @@ -46,13 +54,13 @@ export const ClientProvider: FC<PropsWithChildren> = ({children}) => {
if (!keys) {
return setLoading(false);
}
Client.createFromKeyBundle(keys, {
codecs: [new RemoteAttachmentCodec()],
Client.createFromKeyBundle<SupportedContentTypes>(keys, {
codecs: supportedContentTypes,
enableAlphaMls: true,
env: AppConfig.XMTP_ENV,
})
.then(newClient => {
setClient(newClient);
setClient(newClient as Client<SupportedContentTypes>);
setLoading(false);
})
.catch(() => {
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useConversation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {Conversation} from '@xmtp/react-native-sdk';
import {useEffect, useState} from 'react';
import {SupportedContentTypes} from '../consts/ContentTypes';
import {useClient} from './useClient';

export const useConversation = (topic: string) => {
Expand All @@ -8,7 +9,7 @@ export const useConversation = (topic: string) => {
}
const {client} = useClient();
const [conversation, setConversation] =
useState<Conversation<unknown> | null>(null);
useState<Conversation<SupportedContentTypes> | null>(null);

useEffect(() => {
const getConversation = async () => {
Expand Down
5 changes: 4 additions & 1 deletion src/hooks/useConversationMessages.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import {DecodedMessage} from '@xmtp/react-native-sdk';
import {useEffect, useState} from 'react';
import {SupportedContentTypes} from '../consts/ContentTypes';
import {useConversation} from './useConversation';

export const useConversationMessages = (topic: string) => {
const [messages, setMessages] = useState<DecodedMessage<unknown>[]>([]);
const [messages, setMessages] = useState<
DecodedMessage<SupportedContentTypes>[]
>([]);
const {conversation} = useConversation(topic);

useEffect(() => {
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useGroup.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {Group} from '@xmtp/react-native-sdk/build/lib/Group';
import {useEffect, useState} from 'react';
import {SupportedContentTypes} from '../consts/ContentTypes';
import {useClient} from './useClient';

export const useGroup = (id: string) => {
if (!id) {
throw new Error('useGroup requires an id');
}
const {client} = useClient();
const [group, setGroup] = useState<Group<unknown> | null>(null);
const [group, setGroup] = useState<Group<SupportedContentTypes> | null>(null);

useEffect(() => {
const getGroup = async () => {
Expand Down
Loading
Loading