@@ -20,26 +20,8 @@ export const useUnifiedRepositorySearch = ({ searchString, excludeProjects = fal
20
20
const searchQuery = useSearchRepositories ( { searchString } ) ;
21
21
22
22
const filteredRepos = useMemo ( ( ) => {
23
- const repoMap = new Map < string , SuggestedRepository > ( ) ;
24
- // combine & flatten suggestions and search results, then merge them into a map
25
23
const flattenedRepos = [ suggestedQuery . data || [ ] , searchQuery . data || [ ] ] . flat ( ) ;
26
-
27
- for ( const repo of flattenedRepos ) {
28
- const key = excludeProjects ? repo . url : `${ repo . url } :${ repo . projectId || "" } ` ;
29
-
30
- const newEntry = {
31
- ...( repoMap . get ( key ) || { } ) ,
32
- ...repo ,
33
- } ;
34
- if ( excludeProjects ) {
35
- // TODO: would be great if we can always include repositoryName on SuggestedRepository entities, then we could remove this
36
- newEntry . repositoryName = newEntry . repositoryName || newEntry . projectName ;
37
- newEntry . projectName = undefined ;
38
- }
39
- repoMap . set ( key , newEntry ) ;
40
- }
41
-
42
- return filterRepos ( searchString , Array . from ( repoMap . values ( ) ) ) ;
24
+ return deduplicateAndFilterRepositories ( searchString , excludeProjects , flattenedRepos ) ;
43
25
} , [ excludeProjects , searchQuery . data , searchString , suggestedQuery . data ] ) ;
44
26
45
27
return {
@@ -51,24 +33,52 @@ export const useUnifiedRepositorySearch = ({ searchString, excludeProjects = fal
51
33
} ;
52
34
} ;
53
35
54
- export const filterRepos = ( searchString : string , suggestedRepos : SuggestedRepository [ ] ) => {
55
- let results = suggestedRepos ;
56
- const normalizedSearchString = searchString . trim ( ) ;
57
-
58
- if ( normalizedSearchString . length > 1 ) {
59
- results = suggestedRepos . filter ( ( r ) => {
60
- return `${ r . url } ${ r . projectName || "" } ` . toLowerCase ( ) . includes ( normalizedSearchString ) ;
36
+ export function deduplicateAndFilterRepositories (
37
+ searchString : string ,
38
+ excludeProjects = false ,
39
+ suggestedRepos : SuggestedRepository [ ] ,
40
+ ) : SuggestedRepository [ ] {
41
+ const normalizedSearchString = searchString . trim ( ) . toLowerCase ( ) ;
42
+ const collected = new Set < string > ( ) ;
43
+ const results : SuggestedRepository [ ] = [ ] ;
44
+ const reposWithProject = new Set < string > ( ) ;
45
+ if ( ! excludeProjects ) {
46
+ suggestedRepos . forEach ( ( r ) => {
47
+ if ( r . projectId ) {
48
+ reposWithProject . add ( r . url ) ;
49
+ }
61
50
} ) ;
62
-
63
- if ( results . length === 0 ) {
64
- try {
65
- // If the normalizedSearchString is a URL, and it's not present in the proposed results, "artificially" add it here.
66
- new URL ( normalizedSearchString ) ;
67
- results . push ( { url : normalizedSearchString } ) ;
68
- } catch { }
51
+ }
52
+ for ( const repo of suggestedRepos ) {
53
+ // filter out project entries if excludeProjects is true
54
+ if ( repo . projectId && excludeProjects ) {
55
+ continue ;
56
+ }
57
+ // filter out project-less entries if an entry with a project exists
58
+ if ( ! repo . projectId && reposWithProject . has ( repo . url ) ) {
59
+ continue ;
60
+ }
61
+ // filter out entries that don't match the search string
62
+ if ( ! `${ repo . url } ${ repo . projectName || "" } ` . toLowerCase ( ) . includes ( normalizedSearchString ) ) {
63
+ continue ;
64
+ }
65
+ // filter out duplicates
66
+ const key = `${ repo . url } :${ repo . projectId || "no-project" } ` ;
67
+ if ( collected . has ( key ) ) {
68
+ continue ;
69
69
}
70
+ collected . add ( key ) ;
71
+ results . push ( repo ) ;
72
+ }
73
+
74
+ if ( results . length === 0 ) {
75
+ try {
76
+ // If the normalizedSearchString is a URL, and it's not present in the proposed results, "artificially" add it here.
77
+ new URL ( normalizedSearchString ) ;
78
+ results . push ( { url : normalizedSearchString } ) ;
79
+ } catch { }
70
80
}
71
81
72
82
// Limit what we show to 200 results
73
- return results . length > 200 ? results . slice ( 0 , 200 ) : results ;
74
- } ;
83
+ return results . slice ( 0 , 200 ) ;
84
+ }
0 commit comments