Skip to content

Commit

Permalink
Updated streaming
Browse files Browse the repository at this point in the history
Streaming updates
Fixes for Android
  • Loading branch information
Alex Risch authored and Alex Risch committed Feb 6, 2024
1 parent 354c440 commit e76c63e
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 65 deletions.
21 changes: 16 additions & 5 deletions src/components/ConversationHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {BlurView} from '@react-native-community/blur';
import {HStack, VStack} from 'native-base';
import React, {FC} from 'react';
import {Box, HStack, VStack} from 'native-base';
import React, {FC, PropsWithChildren} from 'react';
import {Platform, Pressable, StyleSheet} from 'react-native';
import {useContactInfo} from '../hooks/useContactInfo';
import {useTypedNavigation} from '../hooks/useTypedNavigation';
Expand All @@ -15,6 +15,17 @@ interface ConversationHeaderProps {
onAvatarPress: () => void;
}

const HeaderContainer: FC<PropsWithChildren> = ({children}) => {
if (Platform.OS === 'ios') {
return (
<BlurView style={styles.blur} blurType="light" blurAmount={5}>
{children}
</BlurView>
);
}
return <Box style={styles.blur}>{children}</Box>;
};

export const ConversationHeader: FC<ConversationHeaderProps> = ({
peerAddress,
onAvatarPress,
Expand All @@ -23,7 +34,7 @@ export const ConversationHeader: FC<ConversationHeaderProps> = ({
const {displayName, avatarUrl} = useContactInfo(peerAddress);

return (
<BlurView style={styles.blur} blurType="light" blurAmount={5}>
<HeaderContainer>
<HStack
w={'100%'}
alignItems={'center'}
Expand Down Expand Up @@ -53,7 +64,7 @@ export const ConversationHeader: FC<ConversationHeaderProps> = ({
/>
</Pressable>
</HStack>
</BlurView>
</HeaderContainer>
);
};

Expand All @@ -63,7 +74,7 @@ const styles = StyleSheet.create({
width: '100%',
zIndex: 10,
elevation: 10,
paddingTop: Platform.OS === 'ios' ? 60 : 0,
paddingTop: Platform.OS === 'ios' ? 60 : 20,
paddingBottom: 8,
},
});
20 changes: 12 additions & 8 deletions src/components/ConversationInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Box, HStack, Image, Pressable, VStack} from 'native-base';
import React, {FC, useCallback, useEffect, useState} from 'react';
import {StyleSheet, TextInput} from 'react-native';
import {Platform, StyleSheet, TextInput} from 'react-native';
import {
Asset,
launchCamera,
Expand Down Expand Up @@ -62,9 +62,9 @@ export const ConversationInput: FC<ConversationInputProps> = ({
mediaType: 'photo',
},
response => {
response.assets?.forEach(asset => {
if (asset.uri) {
setAssetUri(asset);
response.assets?.forEach(resAsset => {
if (resAsset.uri) {
setAssetUri(resAsset);
}
});
},
Expand All @@ -77,9 +77,9 @@ export const ConversationInput: FC<ConversationInputProps> = ({
mediaType: 'photo',
},
response => {
response.assets?.forEach(asset => {
if (asset.uri) {
setAssetUri(asset);
response.assets?.forEach(resAsset => {
if (resAsset.uri) {
setAssetUri(resAsset);
}
});
},
Expand Down Expand Up @@ -129,9 +129,13 @@ export const ConversationInput: FC<ConversationInputProps> = ({
borderWidth={2}
paddingLeft={4}
marginX={2}
paddingY={2}
paddingY={Platform.select({
ios: 2,
android: 0,
})}
bottom={0}
borderRadius={24}
alignItems={'center'}
borderBottomRightRadius={0}>
<TextInput
value={text}
Expand Down
14 changes: 13 additions & 1 deletion src/components/common/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import {IButtonProps, Button as NativeButton} from 'native-base';
import React from 'react';
import {Platform} from 'react-native';

export const Button = (props: IButtonProps) => {
return <NativeButton borderRadius={'120px'} {...props} />;
// Bug related to Android and icons rendered by native-base
const rightIcon = Platform.OS === 'ios' ? props.rightIcon : undefined;
const leftIcon = Platform.OS === 'ios' ? props.leftIcon : undefined;

return (
<NativeButton
borderRadius={'120px'}
{...props}
rightIcon={rightIcon}
leftIcon={leftIcon}
/>
);
};
113 changes: 74 additions & 39 deletions src/screens/ConversationListScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface Conversation {
}

const useData = () => {
const [initialLoading, setInitialLoading] = useState(true);
const [conversations, setConversations] = useState<Conversation[]>([]);
const [requests, setRequests] = useState<Conversation[]>([]);
const {client} = useClient();
Expand All @@ -46,48 +47,65 @@ const useData = () => {
item.permissionType === 'allowed',
);
});
client.conversations.list().then(async convos => {
const allMessages = await Promise.all(
convos.map(async conversation => {
const [messages, consent] = await Promise.all([
conversation.messages(1),
conversation.consentState(),
]);
const content = messages[0].content();
return {
topic: conversation.topic,
lastMessage:
typeof content === 'string'
? content
: messages[0].fallback ?? '',
lastMessageTime: messages[0].sent,
timeDisplay: getMessageTimeDisplay(messages[0].sent),
isRequest: consent !== 'allowed',
address: conversation.peerAddress as `0x${string}`,
};
}),
);
const sorted = allMessages.sort((a, b) => {
return b.lastMessageTime - a.lastMessageTime;
});
setConversations(sorted.filter(convo => !convo.isRequest));
setRequests(sorted.filter(convo => convo.isRequest));
const convos = await client.conversations.list();
const allMessages = await Promise.all(
convos.map(async conversation => {
const [messages, consent] = await Promise.all([
conversation.messages(1),
conversation.consentState(),
]);
const content = messages[0].content();
return {
topic: conversation.topic,
lastMessage:
typeof content === 'string' ? content : messages[0].fallback ?? '',
lastMessageTime: messages[0].sent,
timeDisplay: getMessageTimeDisplay(messages[0].sent),
isRequest: consent !== 'allowed',
address: conversation.peerAddress as `0x${string}`,
};
}),
);
const sorted = allMessages.sort((a, b) => {
return b.lastMessageTime - a.lastMessageTime;
});
setConversations(sorted.filter(convo => !convo.isRequest));
setRequests(sorted.filter(convo => convo.isRequest));
return;
}, [client]);

useEffect(() => {
getAllMessages();
getAllMessages().then(() => setInitialLoading(false));
}, [client, getAllMessages]);

useEffect(() => {
const startStream = () => {
if (!client) {
return;
}
client.conversations.streamAllMessages(async () => {
// TODO: This is a temporary fix to avoid not getting updated messages from state
// Should do this more efficiently
getAllMessages();
client.conversations.streamAllMessages(async message => {
const topic = message.topic;
setConversations(prev => {
const content = message.content();
const messageStringContent =
typeof content === 'string' ? content : message.fallback ?? '';
const existingConversation = prev.find(it => it.topic === topic);
// Handle existing conversations here, new conversations handled in stream
if (existingConversation) {
return prev.map(it =>
it.topic === topic
? {
...it,
lastMessage: messageStringContent,
lastMessageTime: message.sent,
timeDisplay: getMessageTimeDisplay(message.sent),
}
: it,
);
} else {
return prev;
}
});
});
};

Expand All @@ -103,10 +121,25 @@ const useData = () => {
if (!client) {
return;
}
client.conversations.stream(async () => {
// TODO: This is a temporary fix to avoid not getting updated messages from state
// Should do this more efficiently
getAllMessages();
client.conversations.stream(async newConversation => {
const [messages, consent] = await Promise.all([
newConversation.messages(1),
newConversation.consentState(),
]);
const content = messages[0].content();
const messageStringContent =
typeof content === 'string' ? content : messages[0].fallback ?? '';
setConversations(prev => [
{
topic: newConversation.topic,
lastMessage: messageStringContent,
lastMessageTime: messages[0].sent,
timeDisplay: getMessageTimeDisplay(messages[0].sent),
isRequest: consent !== 'allowed',
address: newConversation.peerAddress as `0x${string}`,
},
...prev,
]);
});
};

Expand All @@ -122,6 +155,7 @@ const useData = () => {
return {
messageRequests: requests,
messages: conversations,
initialLoading,
};
};

Expand Down Expand Up @@ -271,7 +305,7 @@ const ListItem: FC<{item: Conversation}> = ({item}) => {
style={{marginRight: 16}}

Check warning on line 305 in src/screens/ConversationListScreen.tsx

View workflow job for this annotation

GitHub Actions / lint

Inline style: { marginRight: 16 }
address={item.address}
/>
<VStack flex={1} style={{justifyContent: 'flex-end'}}>
<VStack flex={1} justifyContent={'flex-end'}>
<Text
numberOfLines={1}
ellipsizeMode="middle"
Expand All @@ -283,8 +317,9 @@ const ListItem: FC<{item: Conversation}> = ({item}) => {
</Text>
</VStack>
<Text
alignSelf={'flex-start'}
typography="text-xs/regular"
style={{alignSelf: 'flex-start', textAlignVertical: 'top'}}>
style={{textAlignVertical: 'top'}}>
{item.timeDisplay}
</Text>
</HStack>
Expand All @@ -299,7 +334,7 @@ export const ConversationListScreen = () => {
const [showPickerModal, setShowPickerModal] = useState(false);
const [showConsentDrawer, setShowConsentDrawer] = useState(false);
const focused = useIsFocused();
const {messages, messageRequests} = useData();
const {messages, messageRequests, initialLoading} = useData();
const {navigate} = useTypedNavigation();

const showPicker = () => {
Expand Down Expand Up @@ -339,7 +374,7 @@ export const ConversationListScreen = () => {
/>
}
ListEmptyComponent={
list === 'ALL_MESSAGES' ? (
list === 'ALL_MESSAGES' && !initialLoading ? (
<VStack
justifyContent={'center'}
alignItems={'center'}
Expand Down
2 changes: 0 additions & 2 deletions src/screens/LoadingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import {Box, Center} from 'native-base';
import React from 'react';
import {ImageBackground} from 'react-native';
import {Screen} from '../components/common/Screen';
// import {Screen} from 'react-native-screens';

export const LoadingScreen = () => {
return (
<Screen containerStlye={{justifyContent: 'center', alignItems: 'center'}}>
{/* <Spinner /> */}
<Center>
<ImageBackground
source={require('../../assets/images/welcome.png')}
Expand Down
27 changes: 17 additions & 10 deletions src/screens/SearchScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {SectionListRenderItem} from 'react-native';
import {AvatarWithFallback} from '../components/AvatarWithFallback';
import {Button} from '../components/common/Button';
import {Icon} from '../components/common/Icon';
import {Pill} from '../components/common/Pill';
import {Screen} from '../components/common/Screen';
import {Text} from '../components/common/Text';
import {AppConfig} from '../consts/AppConfig';
Expand Down Expand Up @@ -141,6 +142,12 @@ export const SearchScreen = () => {
[goBack, navigate, participants],
);

const onGroupStart = useCallback(() => {
const first = participants[0];
goBack();
navigate(ScreenNames.NewConversation, {address: first});
}, [participants, navigate, goBack]);

const items = useMemo(() => {
const {filtered: filteredRecents, mapping: recentMapping} = recents.reduce<{
filtered: Contact[];
Expand Down Expand Up @@ -255,24 +262,24 @@ export const SearchScreen = () => {
paddingX={'8px'}
/>
{AppConfig.GROUPS_ENABLED && (
<VStack paddingX={'16px'} paddingTop={'16px'}>
<VStack paddingX={'16px'} paddingTop={'16px'} w="100%">
<HStack flexWrap={'wrap'}>
{participants.map(participant => {
return (
<Button
variant={'ghost'}
size={'xs'}
onPress={() => removeParticipant(participant)}>
<Text>{formatAddress(participant)}</Text>
</Button>
<Pill
size={'sm'}
onPress={() => removeParticipant(participant)}
text={formatAddress(participant)}
/>
);
})}
</HStack>
{participants.length > 0 && (
<Button
onPress={() => {
// TODO: Create Group
}}>
w={20}
alignSelf={'center'}
size={'xs'}
onPress={onGroupStart}>
{translate('start')}
</Button>
)}
Expand Down

0 comments on commit e76c63e

Please sign in to comment.