@@ -108,6 +108,8 @@ type GetOptionsConfig = {
108
108
action ?: IOUAction ;
109
109
recentAttendees ?: Attendee [ ] ;
110
110
shouldBoldTitleByDefault ?: boolean ;
111
+ shouldSeparateWorkspaceChat ?: boolean ;
112
+ shouldSeparateSelfDMChat ?: boolean ;
111
113
} ;
112
114
113
115
type GetUserToInviteConfig = {
@@ -138,6 +140,8 @@ type Options = {
138
140
personalDetails : ReportUtils . OptionData [ ] ;
139
141
userToInvite : ReportUtils . OptionData | null ;
140
142
currentUserOption : ReportUtils . OptionData | null | undefined ;
143
+ workspaceChats ?: ReportUtils . OptionData [ ] ;
144
+ selfDMChat ?: ReportUtils . OptionData | undefined ;
141
145
} ;
142
146
143
147
type PreviewConfig = { showChatPreviewLine ?: boolean ; forcePolicyNamePreview ?: boolean ; showPersonalDetails ?: boolean } ;
@@ -165,7 +169,7 @@ type OrderReportOptionsConfig = {
165
169
preferRecentExpenseReports ?: boolean ;
166
170
} ;
167
171
168
- type ReportAndPersonalDetailOptions = Pick < Options , 'recentReports' | 'personalDetails' > ;
172
+ type ReportAndPersonalDetailOptions = Pick < Options , 'recentReports' | 'personalDetails' | 'workspaceChats' > ;
169
173
170
174
/**
171
175
* OptionsListUtils is used to build a list options passed to the OptionsList component. Several different UI views can
@@ -1001,6 +1005,23 @@ function orderReportOptionsWithSearch(
1001
1005
) ;
1002
1006
}
1003
1007
1008
+ function orderWorkspaceOptions ( options : ReportUtils . OptionData [ ] ) : ReportUtils . OptionData [ ] {
1009
+ return lodashOrderBy (
1010
+ options ,
1011
+ [
1012
+ ( option ) => {
1013
+ // Put default workspace on top
1014
+ if ( option . isPolicyExpenseChat && option . policyID === activePolicyID ) {
1015
+ return 0 ;
1016
+ }
1017
+
1018
+ return 1 ;
1019
+ } ,
1020
+ ] ,
1021
+ [ 'asc' ] ,
1022
+ ) ;
1023
+ }
1024
+
1004
1025
function sortComparatorReportOptionByArchivedStatus ( option : ReportUtils . OptionData ) {
1005
1026
return option . private_isArchived ? 1 : 0 ;
1006
1027
}
@@ -1028,10 +1049,12 @@ function orderOptions(options: ReportAndPersonalDetailOptions, searchValue?: str
1028
1049
orderedReportOptions = orderReportOptions ( options . recentReports ) ;
1029
1050
}
1030
1051
const orderedPersonalDetailsOptions = orderPersonalDetailsOptions ( options . personalDetails ) ;
1052
+ const orderedWorkspaceChats = orderWorkspaceOptions ( options ?. workspaceChats ?? [ ] ) ;
1031
1053
1032
1054
return {
1033
1055
recentReports : orderedReportOptions ,
1034
1056
personalDetails : orderedPersonalDetailsOptions ,
1057
+ workspaceChats : orderedWorkspaceChats ,
1035
1058
} ;
1036
1059
}
1037
1060
@@ -1140,6 +1163,8 @@ function getValidOptions(
1140
1163
action,
1141
1164
recentAttendees,
1142
1165
shouldBoldTitleByDefault = true ,
1166
+ shouldSeparateSelfDMChat = false ,
1167
+ shouldSeparateWorkspaceChat = false ,
1143
1168
} : GetOptionsConfig = { } ,
1144
1169
) : Options {
1145
1170
const topmostReportId = Navigation . getTopmostReportId ( ) ?? '-1' ;
@@ -1215,6 +1240,12 @@ function getValidOptions(
1215
1240
return true ;
1216
1241
} ) ;
1217
1242
1243
+ let workspaceChats : ReportUtils . OptionData [ ] = [ ] ;
1244
+
1245
+ if ( shouldSeparateWorkspaceChat ) {
1246
+ workspaceChats = allReportOptions . filter ( ( option ) => option . isOwnPolicyExpenseChat && ! option . private_isArchived ) ;
1247
+ }
1248
+
1218
1249
const allPersonalDetailsOptions = includeP2P
1219
1250
? options . personalDetails . filter ( ( detail ) => ! ! detail ?. login && ! ! detail . accountID && ! detail ?. isOptimisticPersonalDetail && ( includeDomainEmail || ! Str . isDomainEmail ( detail . login ) ) )
1220
1251
: [ ] ;
@@ -1325,6 +1356,15 @@ function getValidOptions(
1325
1356
}
1326
1357
1327
1358
const currentUserOption = allPersonalDetailsOptions . find ( ( personalDetailsOption ) => personalDetailsOption . login === currentUserLogin ) ;
1359
+ let selfDMChat : ReportUtils . OptionData | undefined ;
1360
+
1361
+ if ( shouldSeparateWorkspaceChat ) {
1362
+ recentReportOptions = recentReportOptions . filter ( ( option ) => ! option . isPolicyExpenseChat ) ;
1363
+ }
1364
+ if ( shouldSeparateSelfDMChat ) {
1365
+ selfDMChat = recentReportOptions . find ( ( option ) => option . isSelfDM ) ;
1366
+ recentReportOptions = recentReportOptions . filter ( ( option ) => ! option . isSelfDM ) ;
1367
+ }
1328
1368
1329
1369
return {
1330
1370
personalDetails : personalDetailsOptions ,
@@ -1333,6 +1373,8 @@ function getValidOptions(
1333
1373
// User to invite is generated by the search input of a user.
1334
1374
// As this function isn't concerned with any search input yet, this is null (will be set when using filterOptions).
1335
1375
userToInvite : null ,
1376
+ workspaceChats,
1377
+ selfDMChat,
1336
1378
} ;
1337
1379
}
1338
1380
@@ -1573,6 +1615,7 @@ function formatSectionsFromSearchTerm(
1573
1615
filteredPersonalDetails : ReportUtils . OptionData [ ] ,
1574
1616
personalDetails : OnyxEntry < PersonalDetailsList > = { } ,
1575
1617
shouldGetOptionDetails = false ,
1618
+ filteredWorkspaceChats : ReportUtils . OptionData [ ] = [ ] ,
1576
1619
) : SectionForSearchTerm {
1577
1620
// We show the selected participants at the top of the list when there is no search term or maximum number of participants has already been selected
1578
1621
// However, if there is a search term we remove the selected participants from the top of the list unless they are part of the search results
@@ -1598,8 +1641,9 @@ function formatSectionsFromSearchTerm(
1598
1641
const selectedParticipantsWithoutDetails = selectedOptions . filter ( ( participant ) => {
1599
1642
const accountID = participant . accountID ?? null ;
1600
1643
const isPartOfSearchTerm = getPersonalDetailSearchTerms ( participant ) . join ( ' ' ) . toLowerCase ( ) . includes ( cleanSearchTerm ) ;
1601
- const isReportInRecentReports = filteredRecentReports . some ( ( report ) => report . accountID === accountID ) ;
1644
+ const isReportInRecentReports = filteredRecentReports . some ( ( report ) => report . accountID === accountID ) || filteredWorkspaceChats . some ( ( report ) => report . accountID === accountID ) ;
1602
1645
const isReportInPersonalDetails = filteredPersonalDetails . some ( ( personalDetail ) => personalDetail . accountID === accountID ) ;
1646
+
1603
1647
return isPartOfSearchTerm && ! isReportInRecentReports && ! isReportInPersonalDetails ;
1604
1648
} ) ;
1605
1649
@@ -1685,6 +1729,23 @@ function filterReports(reports: ReportUtils.OptionData[], searchTerms: string[])
1685
1729
return filteredReports ;
1686
1730
}
1687
1731
1732
+ function filterWorkspaceChats ( reports : ReportUtils . OptionData [ ] , searchTerms : string [ ] ) : ReportUtils . OptionData [ ] {
1733
+ const filteredReports = searchTerms . reduceRight (
1734
+ ( items , term ) =>
1735
+ filterArrayByMatch ( items , term , ( item ) => {
1736
+ const values : string [ ] = [ ] ;
1737
+ if ( item . text ) {
1738
+ values . push ( item . text ) ;
1739
+ }
1740
+ return uniqFast ( values ) ;
1741
+ } ) ,
1742
+ // We start from all unfiltered reports:
1743
+ reports ,
1744
+ ) ;
1745
+
1746
+ return filteredReports ;
1747
+ }
1748
+
1688
1749
function filterPersonalDetails ( personalDetails : ReportUtils . OptionData [ ] , searchTerms : string [ ] ) : ReportUtils . OptionData [ ] {
1689
1750
return searchTerms . reduceRight (
1690
1751
( items , term ) =>
@@ -1736,6 +1797,34 @@ function filterUserToInvite(options: Omit<Options, 'userToInvite'>, searchValue:
1736
1797
} ) ;
1737
1798
}
1738
1799
1800
+ function filterSelfDMChat ( report : ReportUtils . OptionData , searchTerms : string [ ] ) : ReportUtils . OptionData | undefined {
1801
+ const isMatch = searchTerms . every ( ( term ) => {
1802
+ const values : string [ ] = [ ] ;
1803
+
1804
+ if ( report . text ) {
1805
+ values . push ( report . text ) ;
1806
+ }
1807
+ if ( report . login ) {
1808
+ values . push ( report . login ) ;
1809
+ values . push ( report . login . replace ( CONST . EMAIL_SEARCH_REGEX , '' ) ) ;
1810
+ }
1811
+ if ( report . isThread ) {
1812
+ if ( report . alternateText ) {
1813
+ values . push ( report . alternateText ) ;
1814
+ }
1815
+ } else if ( ! ! report . isChatRoom || ! ! report . isPolicyExpenseChat ) {
1816
+ if ( report . subtitle ) {
1817
+ values . push ( report . subtitle ) ;
1818
+ }
1819
+ }
1820
+
1821
+ // Remove duplicate values and check if the term matches any value
1822
+ return uniqFast ( values ) . some ( ( value ) => value . includes ( term ) ) ;
1823
+ } ) ;
1824
+
1825
+ return isMatch ? report : undefined ;
1826
+ }
1827
+
1739
1828
function filterOptions ( options : Options , searchInputValue : string , config ?: FilterUserToInviteConfig ) : Options {
1740
1829
const parsedPhoneNumber = PhoneNumber . parsePhoneNumber ( LoginUtils . appendCountryCode ( Str . removeSMSDomain ( searchInputValue ) ) ) ;
1741
1830
const searchValue = parsedPhoneNumber . possible && parsedPhoneNumber . number ?. e164 ? parsedPhoneNumber . number . e164 : searchInputValue . toLowerCase ( ) ;
@@ -1753,12 +1842,17 @@ function filterOptions(options: Options, searchInputValue: string, config?: Filt
1753
1842
searchValue ,
1754
1843
config ,
1755
1844
) ;
1845
+ const workspaceChats = filterWorkspaceChats ( options . workspaceChats ?? [ ] , searchTerms ) ;
1846
+
1847
+ const selfDMChat = options . selfDMChat ? filterSelfDMChat ( options . selfDMChat , searchTerms ) : undefined ;
1756
1848
1757
1849
return {
1758
1850
personalDetails,
1759
1851
recentReports,
1760
1852
userToInvite,
1761
1853
currentUserOption,
1854
+ workspaceChats,
1855
+ selfDMChat,
1762
1856
} ;
1763
1857
}
1764
1858
0 commit comments