@@ -9,10 +9,10 @@ import { getGitpodService } from "../service/service";
9
9
import { DropDown2 , DropDown2Element , DropDown2SelectedElement } from "./DropDown2" ;
10
10
import RepositorySVG from "../icons/Repository.svg" ;
11
11
import { ReactComponent as RepositoryIcon } from "../icons/RepositoryWithColor.svg" ;
12
- import { useSuggestedRepositories } from "../data/git-providers/suggested-repositories-query" ;
13
12
import { useFeatureFlag } from "../data/featureflag-query" ;
14
13
import { SuggestedRepository } from "@gitpod/gitpod-protocol" ;
15
14
import { MiddleDot } from "./typography/MiddleDot" ;
15
+ import { filterRepos , useUnifiedRepositorySearch } from "../data/git-providers/unified-repositories-search-query" ;
16
16
17
17
// TODO: Remove this once we've fully enabled `includeProjectsOnCreateWorkspace`
18
18
// flag (caches w/ react-query instead of local storage)
@@ -31,10 +31,12 @@ export default function RepositoryFinder(props: RepositoryFinderProps) {
31
31
const includeProjectsOnCreateWorkspace = useFeatureFlag ( "includeProjectsOnCreateWorkspace" ) ;
32
32
33
33
const [ suggestedContextURLs , setSuggestedContextURLs ] = useState < string [ ] > ( loadSearchData ( ) ) ;
34
- const { data : suggestedRepos , isLoading } = useSuggestedRepositories ( ) ;
34
+
35
+ const [ searchString , setSearchString ] = useState ( "" ) ;
36
+ const { data : repos , isLoading, isSearching } = useUnifiedRepositorySearch ( { searchString } ) ;
35
37
36
38
// TODO: remove this once includeProjectsOnCreateWorkspace is fully enabled
37
- const suggestedRepoURLs = useMemo ( ( ) => {
39
+ const normalizedRepos = useMemo ( ( ) => {
38
40
// If the flag is disabled continue to use suggestedContextURLs, but convert into SuggestedRepository objects
39
41
if ( ! includeProjectsOnCreateWorkspace ) {
40
42
return suggestedContextURLs . map (
@@ -44,8 +46,8 @@ export default function RepositoryFinder(props: RepositoryFinderProps) {
44
46
) ;
45
47
}
46
48
47
- return suggestedRepos || [ ] ;
48
- } , [ suggestedContextURLs , suggestedRepos , includeProjectsOnCreateWorkspace ] ) ;
49
+ return repos ;
50
+ } , [ includeProjectsOnCreateWorkspace , repos , suggestedContextURLs ] ) ;
49
51
50
52
// TODO: remove this once includeProjectsOnCreateWorkspace is fully enabled
51
53
useEffect ( ( ) => {
@@ -60,7 +62,7 @@ export default function RepositoryFinder(props: RepositoryFinderProps) {
60
62
const handleSelectionChange = useCallback (
61
63
( selectedID : string ) => {
62
64
// selectedId is either projectId or repo url
63
- const matchingSuggestion = suggestedRepos ?. find ( ( repo ) => {
65
+ const matchingSuggestion = normalizedRepos ?. find ( ( repo ) => {
64
66
if ( repo . projectId ) {
65
67
return repo . projectId === selectedID ;
66
68
}
@@ -75,12 +77,12 @@ export default function RepositoryFinder(props: RepositoryFinderProps) {
75
77
// If we have no matching suggestion, it's a context URL they typed/pasted in, so just use that as the url
76
78
props . setSelection ( selectedID ) ;
77
79
} ,
78
- [ props , suggestedRepos ] ,
80
+ [ props , normalizedRepos ] ,
79
81
) ;
80
82
81
83
// Resolve the selected context url & project id props to a suggestion entry
82
84
const selectedSuggestion = useMemo ( ( ) => {
83
- let match = suggestedRepos ?. find ( ( repo ) => {
85
+ let match = normalizedRepos ?. find ( ( repo ) => {
84
86
if ( props . selectedProjectID ) {
85
87
return repo . projectId === props . selectedProjectID ;
86
88
}
@@ -105,15 +107,16 @@ export default function RepositoryFinder(props: RepositoryFinderProps) {
105
107
}
106
108
107
109
return match ;
108
- } , [ props . selectedProjectID , props . selectedContextURL , suggestedRepos ] ) ;
110
+ } , [ normalizedRepos , props . selectedContextURL , props . selectedProjectID ] ) ;
109
111
110
112
const getElements = useCallback (
111
113
( searchString : string ) => {
112
- const results = filterRepos ( searchString , suggestedRepoURLs ) ;
113
-
114
+ // TODO: remove once includeProjectsOnCreateWorkspace is fully enabled
114
115
// With the flag off, we only want to show the suggestedContextURLs
115
116
if ( ! includeProjectsOnCreateWorkspace ) {
116
- return results . map (
117
+ // w/o the flag on we still need to filter the repo as the search string changes
118
+ const filteredResults = filterRepos ( searchString , normalizedRepos ) ;
119
+ return filteredResults . map (
117
120
( repo ) =>
118
121
( {
119
122
id : repo . url ,
@@ -133,27 +136,29 @@ export default function RepositoryFinder(props: RepositoryFinderProps) {
133
136
) ;
134
137
}
135
138
136
- // Otherwise we show the suggestedRepos
137
- return results . map ( ( repo ) => {
139
+ // Otherwise we show the suggestedRepos (already filtered)
140
+ return normalizedRepos . map ( ( repo ) => {
138
141
return {
139
142
id : repo . projectId || repo . url ,
140
143
element : < SuggestedRepositoryOption repo = { repo } /> ,
141
144
isSelectable : true ,
142
145
} as DropDown2Element ;
143
146
} ) ;
144
147
} ,
145
- [ includeProjectsOnCreateWorkspace , suggestedRepoURLs ] ,
148
+ [ includeProjectsOnCreateWorkspace , normalizedRepos ] ,
146
149
) ;
147
150
148
151
return (
149
152
< DropDown2
150
153
getElements = { getElements }
151
154
expanded = { ! props . selectedContextURL }
155
+ // we use this to track the search string so we can search for repos via the api
152
156
onSelectionChange = { handleSelectionChange }
153
157
disabled = { props . disabled }
154
158
// Only consider the isLoading prop if we're including projects in list
155
- loading = { isLoading && includeProjectsOnCreateWorkspace }
159
+ loading = { ( isLoading || isSearching ) && includeProjectsOnCreateWorkspace }
156
160
searchPlaceholder = "Paste repository URL or type to find suggestions"
161
+ onSearchChange = { setSearchString }
157
162
>
158
163
< DropDown2SelectedElement
159
164
icon = { RepositorySVG }
@@ -201,7 +206,6 @@ const SuggestedRepositoryOption: FC<SuggestedRepositoryOptionProps> = ({ repo })
201
206
</ >
202
207
) }
203
208
204
- { /* TODO: refine some Text* components a bit to make it easy to set the right colors for dark/light mode */ }
205
209
< span className = "text-sm whitespace-nowrap truncate overflow-ellipsis text-gray-500 dark:text-gray-400" >
206
210
{ stripOffProtocol ( repo . url ) }
207
211
</ span >
@@ -238,28 +242,6 @@ function saveSearchData(searchData: string[]): void {
238
242
}
239
243
}
240
244
241
- function filterRepos ( searchString : string , suggestedRepos : SuggestedRepository [ ] ) {
242
- let results = suggestedRepos ;
243
- const normalizedSearchString = searchString . trim ( ) . toLowerCase ( ) ;
244
-
245
- if ( normalizedSearchString . length > 1 ) {
246
- results = suggestedRepos . filter ( ( r ) => {
247
- return `${ r . url } ${ r . projectName || "" } ` . toLowerCase ( ) . includes ( normalizedSearchString ) ;
248
- } ) ;
249
-
250
- if ( results . length === 0 ) {
251
- try {
252
- // If the normalizedSearchString is a URL, and it's not present in the proposed results, "artificially" add it here.
253
- new URL ( normalizedSearchString ) ;
254
- results . push ( { url : normalizedSearchString } ) ;
255
- } catch { }
256
- }
257
- }
258
-
259
- // Limit what we show to 200 results
260
- return results . length > 200 ? results . slice ( 0 , 200 ) : results ;
261
- }
262
-
263
245
function stripOffProtocol ( url : string ) : string {
264
246
if ( ! url . startsWith ( "http" ) ) {
265
247
return url ;
0 commit comments