Skip to content

Commit d853924

Browse files
committed
chatroom-list
1 parent bc7ddf6 commit d853924

File tree

42 files changed

+3014
-1497
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3014
-1497
lines changed

packages/components/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# @baseapp-frontend/components
22

3+
## 1.4.4
4+
5+
### Minor Changes
6+
7+
- Added roomslist components and illustrations
8+
9+
### Patch Changes
10+
11+
- Updated dependencies
12+
- @baseapp-frontend/design-system@1.2.0
13+
314
## 1.4.3
415

516
### Patch Changes
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Text } from '@baseapp-frontend/design-system/components/native/typographies'
2+
import { View } from '@baseapp-frontend/design-system/components/native/views'
3+
import { useTheme } from '@baseapp-frontend/design-system/providers/native'
4+
5+
import { createStyles } from './styles'
6+
import { EmptyViewProps } from './types'
7+
8+
const EmptyView = ({ icon, title, message }: EmptyViewProps) => {
9+
const theme = useTheme()
10+
const styles = createStyles(theme)
11+
12+
return (
13+
<View style={styles.container}>
14+
{icon && <View style={styles.imageWrapper}>{icon}</View>}
15+
<View style={styles.textWrapper}>
16+
{title && (
17+
<Text variant="subtitle2" style={styles.text}>
18+
{title}
19+
</Text>
20+
)}
21+
{message && (
22+
<Text variant="caption" style={styles.text}>
23+
{message}
24+
</Text>
25+
)}
26+
</View>
27+
</View>
28+
)
29+
}
30+
31+
export default EmptyView
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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+
flex: 1,
9+
padding: 32,
10+
flexDirection: 'column',
11+
gap: 12,
12+
justifyContent: 'center',
13+
alignItems: 'center',
14+
},
15+
imageWrapper: {
16+
flex: 1,
17+
alignItems: 'center',
18+
},
19+
textWrapper: {
20+
flex: 1,
21+
width: 393,
22+
padding: 16,
23+
justifyContent: 'flex-end',
24+
alignItems: 'center',
25+
gap: 10,
26+
},
27+
text: {
28+
color: theme.colors.object.low,
29+
},
30+
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { ReactNode } from 'react'
2+
3+
import { StyleProp, ViewStyle } from 'react-native'
4+
5+
export interface EmptyViewProps {
6+
icon?: ReactNode
7+
title: string
8+
message?: string
9+
style?: StyleProp<ViewStyle>
10+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as EmptyView } from './EmptyView'
2+
export type * from './EmptyView/types'
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { FC, Suspense, useState, useTransition } from 'react'
2+
3+
import { SearchInput } from '@baseapp-frontend/design-system/components/native/inputs'
4+
import { Tab, Tabs } from '@baseapp-frontend/design-system/components/native/tabs'
5+
import { Text } from '@baseapp-frontend/design-system/components/native/typographies'
6+
import { PageViewWithHeader, View } from '@baseapp-frontend/design-system/components/native/views'
7+
import { useTheme } from '@baseapp-frontend/design-system/providers/native'
8+
import { useAppStateSubscription } from '@baseapp-frontend/utils/hooks/useAppStateSubscription'
9+
10+
import { useForm } from 'react-hook-form'
11+
import { useLazyLoadQuery, useRelayEnvironment } from 'react-relay'
12+
13+
import { ChatRoomsQuery as ChatRoomsQueryType } from '../../../../__generated__/ChatRoomsQuery.graphql'
14+
import { RoomsListFragment$key } from '../../../../__generated__/RoomsListFragment.graphql'
15+
import { useRoomsList } from '../../common'
16+
import { ChatRoomsQuery } from '../../common/graphql/queries/ChatRoomsQuery'
17+
import { NewChatButton } from '../NewChatButton'
18+
import RoomsList from '../RoomsList'
19+
import { CHAT_TAB_LABEL, CHAT_TAB_VALUES } from '../RoomsList/RoomsListComponent/constants'
20+
import { ChatTabValues } from '../RoomsList/RoomsListComponent/types'
21+
import { useRoomListSubscription } from '../graphql/subscriptions/useRoomListSubscription'
22+
import { createStyles } from './styles'
23+
24+
const ChatRooms: FC = () => {
25+
const theme = useTheme()
26+
const styles = createStyles(theme)
27+
const { control, reset } = useForm({ defaultValues: { search: '' } })
28+
const [selectedTab, setSelectedTab] = useState<string>(CHAT_TAB_VALUES.active)
29+
const [searchParam, setSearchParam] = useState('')
30+
const [isPending, startTransition] = useTransition()
31+
const chatRoomQueryData = useLazyLoadQuery<ChatRoomsQueryType>(
32+
ChatRoomsQuery,
33+
{},
34+
{ fetchPolicy: 'store-and-network' },
35+
)
36+
const { data, refetch } = useRoomsList(chatRoomQueryData?.me?.profile as RoomsListFragment$key)
37+
38+
const handleSearchChange = (text: string) => {
39+
if (isPending) return
40+
startTransition(() => {
41+
setSearchParam(text)
42+
})
43+
}
44+
45+
const resetInput = () => {
46+
setSearchParam('')
47+
reset({ search: '' })
48+
}
49+
50+
const environment = useRelayEnvironment()
51+
useRoomListSubscription({ profileId: data?.id, connections: [], environment })
52+
53+
const handleChange = (newValue: string) => {
54+
setSelectedTab(newValue as ChatTabValues)
55+
}
56+
57+
useAppStateSubscription(() => {
58+
refetch(
59+
{
60+
q: searchParam,
61+
unreadMessages: selectedTab === CHAT_TAB_VALUES.unread,
62+
archived: selectedTab === CHAT_TAB_VALUES.archived,
63+
},
64+
{ fetchPolicy: 'store-and-network' },
65+
)
66+
})
67+
68+
return (
69+
<PageViewWithHeader>
70+
<View style={styles.container}>
71+
<Text variant="h4">Messages</Text>
72+
<SearchInput
73+
placeholder="Search"
74+
onChangeText={handleSearchChange}
75+
control={control}
76+
name="search"
77+
searchParam={searchParam}
78+
resetInput={resetInput}
79+
/>
80+
81+
<Tabs value={selectedTab} onChange={handleChange} style={styles.tabs}>
82+
<Tab
83+
label={CHAT_TAB_LABEL.active}
84+
value={CHAT_TAB_VALUES.active}
85+
aria-label="Active messages tab"
86+
/>
87+
<Tab
88+
label={CHAT_TAB_LABEL.unread}
89+
value={CHAT_TAB_VALUES.unread}
90+
aria-label="Unread messages tab"
91+
/>
92+
<Tab
93+
label={CHAT_TAB_LABEL.groups}
94+
value={CHAT_TAB_VALUES.groups}
95+
aria-label="Groups messages tab"
96+
/>
97+
<Tab
98+
label={CHAT_TAB_LABEL.archived}
99+
value={CHAT_TAB_VALUES.archived}
100+
aria-label="Archived messages tab"
101+
/>
102+
</Tabs>
103+
{
104+
// TODO: Handle groups tab separately will be implemented later
105+
selectedTab === CHAT_TAB_VALUES.groups ? (
106+
<Text>Groups tab is not implemented yet.</Text>
107+
) : (
108+
<RoomsList
109+
targetRef={chatRoomQueryData}
110+
searchParam={searchParam}
111+
selectedTab={selectedTab}
112+
/>
113+
)
114+
}
115+
<NewChatButton />
116+
</View>
117+
</PageViewWithHeader>
118+
)
119+
}
120+
121+
const SuspendedChatRooms = () => (
122+
<Suspense>
123+
<ChatRooms />
124+
</Suspense>
125+
)
126+
127+
export default SuspendedChatRooms
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
flexGrow: 1,
10+
flex: 1,
11+
position: 'relative',
12+
},
13+
chatRoomsContainer: {
14+
flexGrow: 1,
15+
},
16+
tabs: {
17+
justifyContent: 'space-evenly',
18+
gap: 0,
19+
},
20+
})
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react'
2+
3+
import { FabButton } from '@baseapp-frontend/design-system/components/native/buttons'
4+
import { useTheme } from '@baseapp-frontend/design-system/providers/native'
5+
6+
import { useRouter } from 'expo-router'
7+
8+
const NewChatButton = () => {
9+
const theme = useTheme()
10+
const router = useRouter()
11+
12+
const navigateToCreateRoom = () => router.push('/create-room')
13+
14+
return (
15+
<FabButton
16+
onPress={navigateToCreateRoom}
17+
iconName="add"
18+
iconSize={28}
19+
iconColor={theme.colors.primary.contrast}
20+
/>
21+
)
22+
}
23+
24+
export { NewChatButton }

0 commit comments

Comments
 (0)