11import { useFocusEffect } from '@react-navigation/native' ;
22import { policyChatRoomsSelector } from '@selectors/Report' ;
3- import { FlashList } from '@shopify/flash-list' ;
4- import type { ListRenderItemInfo } from '@shopify/flash-list' ;
53import React from 'react' ;
64import { View } from 'react-native' ;
5+ import Avatar from '@components/Avatar' ;
76import Button from '@components/Button' ;
87import HeaderWithBackButton from '@components/HeaderWithBackButton' ;
98import Icon from '@components/Icon' ;
109import { usePersonalDetails } from '@components/OnyxListItemProvider' ;
1110import ScreenWrapper from '@components/ScreenWrapper' ;
11+ import SelectionList from '@components/SelectionList' ;
12+ import TableListItem from '@components/SelectionList/ListItem/TableListItem' ;
13+ import type { ListItem } from '@components/SelectionList/types' ;
1214import Text from '@components/Text' ;
1315import useArchivedReportsIdSet from '@hooks/useArchivedReportsIdSet' ;
1416import { useMemoizedLazyExpensifyIcons , useMemoizedLazyIllustrations } from '@hooks/useLazyAsset' ;
@@ -18,6 +20,7 @@ import usePermissions from '@hooks/usePermissions';
1820import usePolicy from '@hooks/usePolicy' ;
1921import useReportAttributes from '@hooks/useReportAttributes' ;
2022import useResponsiveLayout from '@hooks/useResponsiveLayout' ;
23+ import useStyleUtils from '@hooks/useStyleUtils' ;
2124import useTheme from '@hooks/useTheme' ;
2225import useThemeStyles from '@hooks/useThemeStyles' ;
2326import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle' ;
@@ -34,70 +37,21 @@ import CONST from '@src/CONST';
3437import ONYXKEYS from '@src/ONYXKEYS' ;
3538import ROUTES from '@src/ROUTES' ;
3639import type SCREENS from '@src/SCREENS' ;
37- import type { PersonalDetails , Report } from '@src/types/onyx' ;
38- import WorkspaceRoomsListItem from './WorkspaceRoomsListItem' ;
3940
4041type WorkspaceRoomsPageProps = PlatformStackScreenProps < WorkspaceSplitNavigatorParamList , typeof SCREENS . WORKSPACE . ROOMS > ;
4142
42- /**
43- * Row data for a single workspace room rendered in the list.
44- */
45- type WorkspaceRoomsRow = {
46- /** The underlying report representing the room. */
47- report : Report ;
48-
49- /** Resolved display name of the room. */
50- roomName : string ;
51-
52- /** Personal details of the room owner, if available. */
53- ownerDetails : PersonalDetails | undefined ;
54-
55- /** Display name for the room owner, or empty string when missing. */
56- ownerDisplayName : string ;
57-
58- /** Number of members shown next to the room. */
59- memberCount : number ;
43+ type RoomListItem = ListItem & {
44+ reportID : string ;
6045} ;
6146
62- function RowSeparator ( ) {
63- return < View style = { { height : 8 } } /> ;
64- }
65-
66- function ListHeader ( ) {
67- const { translate} = useLocalize ( ) ;
68- const styles = useThemeStyles ( ) ;
69- const theme = useTheme ( ) ;
70- const icons = useMemoizedLazyExpensifyIcons ( [ 'Profile' ] ) ;
71-
72- return (
73- < View style = { [ styles . flexRow , styles . alignItemsCenter , styles . p4 , styles . gap3 ] } >
74- < View style = { [ styles . flexRow , styles . alignItemsCenter , styles . gap3 , styles . flex3 ] } >
75- < View style = { [ styles . alignItemsCenter , styles . justifyContentCenter , { width : variables . avatarSizeNormal } ] } >
76- < Icon
77- src = { icons . Profile }
78- width = { variables . iconSizeSmall }
79- height = { variables . iconSizeSmall }
80- fill = { theme . icon }
81- />
82- </ View >
83- < Text style = { styles . textLabelSupporting } > { translate ( 'common.name' ) } </ Text >
84- </ View >
85- < View style = { styles . flex2 } >
86- < Text style = { styles . textLabelSupporting } > { translate ( 'common.createdBy' ) } </ Text >
87- </ View >
88- < View style = { styles . flex1 } >
89- < Text style = { styles . textLabelSupporting } > { translate ( 'common.members' ) } </ Text >
90- </ View >
91- </ View >
92- ) ;
93- }
94-
9547function WorkspaceRoomsPage ( { route} : WorkspaceRoomsPageProps ) {
9648 const { translate, localeCompare} = useLocalize ( ) ;
9749 const styles = useThemeStyles ( ) ;
50+ const StyleUtils = useStyleUtils ( ) ;
51+ const theme = useTheme ( ) ;
9852 const { shouldUseNarrowLayout} = useResponsiveLayout ( ) ;
9953 const { isBetaEnabled} = usePermissions ( ) ;
100- const icons = useMemoizedLazyExpensifyIcons ( [ 'Plus' ] ) ;
54+ const headerIcons = useMemoizedLazyExpensifyIcons ( [ 'Plus' , 'Profile '] ) ;
10155 const illustrations = useMemoizedLazyIllustrations ( [ 'Hashtag' ] ) ;
10256 const policyID = route . params . policyID ;
10357 const policy = usePolicy ( policyID ) ;
@@ -115,24 +69,73 @@ function WorkspaceRoomsPage({route}: WorkspaceRoomsPageProps) {
11569 [ policyID ] ,
11670 ) ;
11771
118- const rows : WorkspaceRoomsRow [ ] = ( policyReports ?? [ ] )
72+ const data : RoomListItem [ ] = ( policyReports ?? [ ] )
11973 . filter ( ( report ) => ! archivedReportsIdSet . has ( `${ ONYXKEYS . COLLECTION . REPORT_NAME_VALUE_PAIRS } ${ report . reportID } ` ) && ! isHiddenForCurrentUser ( report ) )
12074 . map ( ( report ) => {
12175 const ownerDetails = report . ownerAccountID ? ( personalDetails ?. [ report . ownerAccountID ] ?? undefined ) : undefined ;
76+ const ownerDisplayName = ownerDetails ? getDisplayNameOrDefault ( ownerDetails ) : '' ;
77+ const roomName = getReportName ( report , reportAttributes ) ;
78+ const memberCount = getParticipantsAccountIDsForDisplay ( report , true , false , false , undefined , personalDetails ) . length ;
12279 return {
123- report,
124- roomName : getReportName ( report , reportAttributes ) ,
125- ownerDetails,
126- ownerDisplayName : ownerDetails ? getDisplayNameOrDefault ( ownerDetails ) : '' ,
127- memberCount : getParticipantsAccountIDsForDisplay ( report , true , false , false , undefined , personalDetails ) . length ,
80+ keyForList : report . reportID ,
81+ text : roomName ,
82+ reportID : report . reportID ,
83+ rightElement : (
84+ < >
85+ < View style = { [ styles . flexRow , styles . alignItemsCenter , styles . gap2 , styles . flex2 ] } >
86+ { ! ! ownerDetails && (
87+ < >
88+ < Avatar
89+ source = { ownerDetails . avatar }
90+ avatarID = { ownerDetails . accountID }
91+ name = { ownerDisplayName }
92+ type = { CONST . ICON_TYPE_AVATAR }
93+ size = { CONST . AVATAR_SIZE . SMALLER }
94+ />
95+ < Text
96+ numberOfLines = { 1 }
97+ style = { styles . flexShrink1 }
98+ >
99+ { ownerDisplayName }
100+ </ Text >
101+ </ >
102+ ) }
103+ </ View >
104+ < View style = { styles . flex1 } >
105+ < Text > { memberCount } </ Text >
106+ </ View >
107+ </ >
108+ ) ,
128109 } ;
129110 } )
130- . sort ( ( a , b ) => localeCompare ( a . roomName , b . roomName ) ) ;
111+ . sort ( ( a , b ) => localeCompare ( a . text ?? '' , b . text ?? '' ) ) ;
131112
132113 useFocusEffect ( ( ) => {
133114 openWorkspaceRoomsPage ( policyID ) ;
134115 } ) ;
135116
117+ const customListHeader = (
118+ < View style = { [ styles . flexRow , styles . alignItemsCenter , styles . mh5 , styles . ph4 , styles . pv3 ] } >
119+ < View style = { [ styles . alignItemsCenter , styles . justifyContentCenter , StyleUtils . getAvatarWidthStyle ( CONST . AVATAR_SIZE . DEFAULT ) ] } >
120+ < Icon
121+ src = { headerIcons . Profile }
122+ width = { variables . iconSizeSmall }
123+ height = { variables . iconSizeSmall }
124+ fill = { theme . icon }
125+ />
126+ </ View >
127+ < View style = { styles . flex1 } >
128+ < Text style = { styles . textLabelSupporting } > { translate ( 'common.name' ) } </ Text >
129+ </ View >
130+ < View style = { styles . flex2 } >
131+ < Text style = { styles . textLabelSupporting } > { translate ( 'common.createdBy' ) } </ Text >
132+ </ View >
133+ < View style = { [ styles . flex1 , styles . mr7 ] } >
134+ < Text style = { styles . textLabelSupporting } > { translate ( 'common.members' ) } </ Text >
135+ </ View >
136+ </ View >
137+ ) ;
138+
136139 return (
137140 < AccessOrNotFoundWrapper
138141 policyID = { policyID }
@@ -157,29 +160,19 @@ function WorkspaceRoomsPage({route}: WorkspaceRoomsPageProps) {
157160 success
158161 isDisabled
159162 onPress = { ( ) => { } }
160- icon = { icons . Plus }
163+ icon = { headerIcons . Plus }
161164 text = { translate ( 'common.create' ) }
162165 />
163166 </ HeaderWithBackButton >
164167
165- < View style = { [ styles . flex1 , styles . pv3 , styles . ph5 ] } >
166- < FlashList
167- data = { rows }
168- keyExtractor = { ( row ) => row . report . reportID }
169- ItemSeparatorComponent = { RowSeparator }
170- ListHeaderComponent = { ListHeader }
171- renderItem = { ( { item} : ListRenderItemInfo < WorkspaceRoomsRow > ) => (
172- < WorkspaceRoomsListItem
173- report = { item . report }
174- roomName = { item . roomName }
175- ownerDetails = { item . ownerDetails }
176- ownerDisplayName = { item . ownerDisplayName }
177- memberCount = { item . memberCount }
178- onPress = { ( ) => Navigation . navigate ( ROUTES . REPORT_WITH_ID . getRoute ( item . report . reportID ) ) }
179- />
180- ) }
181- />
182- </ View >
168+ < SelectionList < RoomListItem >
169+ data = { data }
170+ ListItem = { TableListItem }
171+ onSelectRow = { ( item ) => Navigation . navigate ( ROUTES . REPORT_WITH_ID . getRoute ( item . reportID ) ) }
172+ customListHeader = { customListHeader }
173+ shouldHeaderBeInsideList
174+ shouldShowRightCaret
175+ />
183176 </ ScreenWrapper >
184177 </ AccessOrNotFoundWrapper >
185178 ) ;
0 commit comments