Skip to content

Commit b009cd8

Browse files
committed
Single chat components
1 parent d853924 commit b009cd8

File tree

9 files changed

+199
-1
lines changed

9 files changed

+199
-1
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { useCurrentProfile } from '@baseapp-frontend/authentication'
2+
import { AvatarWithPlaceholder } from '@baseapp-frontend/design-system/components/native/avatars'
3+
import { Text } from '@baseapp-frontend/design-system/components/native/typographies'
4+
import { View } from '@baseapp-frontend/design-system/components/native/views'
5+
import { useTheme } from '@baseapp-frontend/design-system/providers/native'
6+
7+
import { router } from 'expo-router'
8+
import { Pressable } from 'react-native'
9+
import { ConnectionHandler, useFragment } from 'react-relay'
10+
11+
import { ProfileItemFragment$key } from '../../../../../../__generated__/ProfileItemFragment.graphql'
12+
import { ProfileItemFragment } from '../../../../../profiles/common'
13+
import { useCreateChatRoomMutation } from '../../../../common'
14+
import { createStyles } from './styles'
15+
16+
const ChatRoomListItem = ({ profile: profileRef }: { profile: ProfileItemFragment$key }) => {
17+
const theme = useTheme()
18+
const styles = createStyles(theme)
19+
20+
const node = useFragment(ProfileItemFragment, profileRef)
21+
const [commit] = useCreateChatRoomMutation()
22+
23+
const { currentProfile } = useCurrentProfile()
24+
25+
const handleRoomCompleted = (roomRef: string) => {
26+
router.push(`/rooms/${roomRef}`)
27+
}
28+
29+
const handleRoomCreation = () => {
30+
if (currentProfile?.id) {
31+
commit({
32+
variables: {
33+
input: { profileId: currentProfile.id, participants: [node?.id] },
34+
connections: [
35+
ConnectionHandler.getConnectionID(currentProfile.id, 'roomsList_chatRooms', {
36+
unreadMessages: false,
37+
archived: false,
38+
q: '',
39+
}),
40+
],
41+
},
42+
onCompleted: (response) => {
43+
const roomId = response?.chatRoomCreate?.room?.node?.id
44+
if (roomId) {
45+
handleRoomCompleted(roomId)
46+
}
47+
},
48+
})
49+
}
50+
}
51+
52+
return (
53+
<Pressable key={`chat-room-item-${node?.id}`} onPress={handleRoomCreation}>
54+
<View style={styles.cardContainer}>
55+
<View>
56+
<AvatarWithPlaceholder imgSource={node?.image?.url} />
57+
</View>
58+
<View>
59+
<Text variant="subtitle2">{node?.name}</Text>
60+
<Text variant="caption">
61+
{node?.urlPath?.path && `@${node?.urlPath.path?.replace('/', '')}`}
62+
</Text>
63+
</View>
64+
</View>
65+
</Pressable>
66+
)
67+
}
68+
69+
export default ChatRoomListItem
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Theme } from '@baseapp-frontend/design-system/styles/native'
2+
3+
import { StyleSheet } from 'react-native'
4+
5+
export const createStyles = (theme: Theme) =>
6+
StyleSheet.create({
7+
cardContainer: {
8+
flexDirection: 'row',
9+
alignItems: 'center',
10+
gap: 12,
11+
paddingVertical: 12,
12+
flex: 1,
13+
backgroundColor: theme.colors.surface.background,
14+
},
15+
})
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React, { Suspense, useEffect, useRef, useTransition } from 'react'
2+
3+
import { View } from '@baseapp-frontend/design-system/components/native/views'
4+
import { useTheme } from '@baseapp-frontend/design-system/providers/native'
5+
6+
import { Dimensions } from 'react-native'
7+
import { FlatList } from 'react-native-gesture-handler'
8+
9+
import { useAllProfilesList } from '../../../../profiles/common'
10+
import { withChatRoomProvider } from '../../../common'
11+
import SearchNotFoundState from '../../SearchNotFoundState'
12+
import ChatRoomListItem from './CreateRoomListItem'
13+
import { createStyles } from './styles'
14+
import { CreateRoomListProps } from './types'
15+
16+
const CreateRoomList = ({ targetRef, searchParam }: CreateRoomListProps) => {
17+
const theme = useTheme()
18+
const styles = createStyles(theme)
19+
20+
const [isPending, startTransition] = useTransition()
21+
const { data, refetch, loadNext, hasNext } = useAllProfilesList(targetRef)
22+
23+
const profiles = data?.allProfiles?.edges ?? []
24+
const layoutTriggeredRef = useRef(false)
25+
const screenHeight = Dimensions.get('window').height
26+
27+
const loadNextBasedOnHeight = (height: number) => {
28+
if (!layoutTriggeredRef.current && hasNext && height < screenHeight) {
29+
layoutTriggeredRef.current = true
30+
loadNext(10)
31+
}
32+
}
33+
34+
const handleEmptySearch = () => {
35+
if (searchParam && !isPending && !profiles.length) {
36+
return <SearchNotFoundState />
37+
}
38+
return null
39+
}
40+
41+
useEffect(() => {
42+
layoutTriggeredRef.current = false
43+
startTransition(() => {
44+
refetch({ q: searchParam })
45+
})
46+
}, [refetch, searchParam])
47+
48+
return (
49+
<View style={styles.flatListWrapper}>
50+
<FlatList
51+
data={profiles}
52+
keyExtractor={(item, i) => (item && item.node?.id) || i.toString()}
53+
renderItem={({ item }) => (item?.node ? <ChatRoomListItem profile={item.node} /> : null)}
54+
onEndReached={() => {
55+
if (hasNext) loadNext(10)
56+
}}
57+
onEndReachedThreshold={0.8}
58+
onContentSizeChange={(width, height) => loadNextBasedOnHeight(height)}
59+
contentContainerStyle={styles.contentContainer}
60+
style={styles.flatList}
61+
keyboardShouldPersistTaps="handled"
62+
ListEmptyComponent={handleEmptySearch}
63+
/>
64+
</View>
65+
)
66+
}
67+
68+
const CreateRoomListWithProvider = withChatRoomProvider(CreateRoomList)
69+
70+
const SuspendedCreateRoomList = (props: CreateRoomListProps) => (
71+
<Suspense>
72+
<CreateRoomListWithProvider {...props} />
73+
</Suspense>
74+
)
75+
76+
export default SuspendedCreateRoomList
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Theme } from '@baseapp-frontend/design-system/styles/native'
2+
3+
import { StyleSheet } from 'react-native'
4+
5+
export const createStyles = (theme: Theme) =>
6+
StyleSheet.create({
7+
flatListWrapper: {
8+
flex: 1,
9+
},
10+
contentContainer: {
11+
paddingBottom: 16,
12+
width: '100%',
13+
},
14+
flatList: {
15+
flex: 1,
16+
width: '100%',
17+
backgroundColor: theme.colors.surface.background,
18+
},
19+
})
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// import { CreateRoomPageQuery$data } from '__generated__/CreateRoomPageQuery.graphql'
2+
3+
export interface CreateRoomListProps {
4+
targetRef: any // CreateRoomPageQuery$data
5+
searchParam: string
6+
}

packages/components/modules/messages/native/SingleChatCreate/index.tsx

Whitespace-only changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Theme } from '@baseapp-frontend/design-system/styles/native'
2+
3+
import { StyleSheet } from 'react-native'
4+
5+
export const createStyles = (theme: Theme) =>
6+
StyleSheet.create({
7+
container: {
8+
backgroundColor: theme.colors.surface.background,
9+
flex: 1,
10+
flexGrow: 1,
11+
paddingHorizontal: 12,
12+
},
13+
})

packages/components/modules/messages/native/SingleChatCreate/types.ts

Whitespace-only changes.

packages/components/modules/messages/native/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ export * from './graphql/subscriptions/useMessagesListSubscription'
33
export * from './graphql/subscriptions/useRoomListSubscription'
44
export { default as ChatRooms } from './ChatRooms'
55
export { default as RoomsList } from './RoomsList'
6-
export { default as SearchNotFoundState } from './SearchNotFoundState'
6+
export { default as CreateRoomList } from './SingleChatCreate/CreateRoomList'

0 commit comments

Comments
 (0)