@@ -29,10 +29,17 @@ interface ProjectsState {
2929 selectedIndex ?: number ;
3030 searchMode ?: boolean ;
3131 searchQuery ?: string ;
32- searchResults ?: pxt . CodeCard [ ] ;
32+ searchResults ?: SearchCard [ ] ;
3333}
3434
3535const SEARCH_CATEGORY = "__search__" ;
36+ type SearchCard = pxt . CodeCard & { projectHeader ?: pxt . workspace . Header } ;
37+
38+ function getProjectDescriptionFromConfig ( configText : string ) : string {
39+ const config = pxt . Util . jsonTryParse ( configText ) as pxt . PackageConfig ;
40+ const description = config ?. description ?. trim ( ) ;
41+ return description || undefined ;
42+ }
3643
3744export class Projects extends auth . Component < ISettingsProps , ProjectsState > {
3845 protected searchRequestId = 0 ;
@@ -111,14 +118,14 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
111118 return galleries ;
112119 }
113120
114- private collectGalleryCards ( galleries : pxt . Map < string | pxt . GalleryProps > ) : pxt . CodeCard [ ] {
121+ private collectGalleryCards ( galleries : pxt . Map < string | pxt . GalleryProps > ) : SearchCard [ ] {
115122 return this . collectGallerySearchEntries ( galleries ) . cards ;
116123 }
117124
118125 private collectGallerySearchEntries ( galleries : pxt . Map < string | pxt . GalleryProps > ) {
119- const cards : pxt . CodeCard [ ] = [ ] ;
126+ const cards : SearchCard [ ] = [ ] ;
120127 const entries = [ ] as { id : string ; name : string ; description ?: string ; tags ?: string ; searchTerms ?: string ; } [ ] ;
121- const cardMap : pxt . Map < pxt . CodeCard > = { } ;
128+ const cardMap : pxt . Map < SearchCard > = { } ;
122129 const seen = new Set < string > ( ) ;
123130
124131 Object . keys ( galleries ) . forEach ( galleryName => {
@@ -153,7 +160,7 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
153160 return headers . filter ( h => ! pxt . tutorial . shouldFilterProject ( h . tutorial ?. metadata ) ) ;
154161 }
155162
156- private projectHeaderToSearchCard ( header : pxt . workspace . Header ) : pxt . CodeCard & { projectHeader : pxt . workspace . Header } {
163+ private projectHeaderToSearchCard ( header : pxt . workspace . Header ) : SearchCard {
157164 const tutorialStep =
158165 header . tutorial ? header . tutorial . tutorialStep
159166 : header . tutorialCompleted ? header . tutorialCompleted . steps - 1
@@ -300,8 +307,8 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
300307 } ) ;
301308 }
302309
303- private handleSearchCardClick ( e : any , scr : pxt . CodeCard , index ?: number ) {
304- const header = ( scr as pxt . CodeCard & { projectHeader ?: pxt . workspace . Header } ) . projectHeader ;
310+ private handleSearchCardClick ( e : any , scr : SearchCard , index ?: number ) {
311+ const header = scr . projectHeader ;
305312 if ( header ) {
306313 this . chgHeader ( header ) ;
307314 return ;
@@ -314,8 +321,8 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
314321 this . setSelected ( SEARCH_CATEGORY , index ) ;
315322 }
316323
317- private handleSearchDetailClick ( scr : pxt . CodeCard , action ?: pxt . CodeCardAction ) {
318- const header = ( scr as pxt . CodeCard & { projectHeader ?: pxt . workspace . Header } ) . projectHeader ;
324+ private handleSearchDetailClick ( scr : SearchCard , action ?: pxt . CodeCardAction ) {
325+ const header = scr . projectHeader ;
319326 if ( header && ! action ) {
320327 this . chgHeader ( header ) ;
321328 return ;
@@ -324,6 +331,11 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
324331 this . chgGallery ( scr , action ) ;
325332 }
326333
334+ private getLocalProjectDescription ( header : pxt . workspace . Header ) : string {
335+ const configText = this . getData ( `text:${ header . id } /${ pxt . CONFIG_NAME } ` ) as string ;
336+ return getProjectDescriptionFromConfig ( configText ) ;
337+ }
338+
327339 scrollElementIntoViewIfNeeded ( domNode : Element ) {
328340 let containerDomNode = ReactDOM . findDOMNode ( this . refs [ 'homeContainer' ] ) ;
329341 // Determine if `domNode` fully fits inside `containerDomNode`.
@@ -385,6 +397,10 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
385397 const searchResults = this . state . searchResults || [ ] ;
386398 const searchSelectedIndex = this . state . selectedCategory === SEARCH_CATEGORY ? this . state . selectedIndex : undefined ;
387399 const selectedSearchCard = searchSelectedIndex !== undefined ? searchResults [ searchSelectedIndex ] : undefined ;
400+ const selectedSearchProjectHeader = selectedSearchCard ?. projectHeader ;
401+ const selectedSearchDescription = selectedSearchProjectHeader
402+ ? this . getLocalProjectDescription ( selectedSearchProjectHeader ) || selectedSearchCard ?. description
403+ : selectedSearchCard ?. description ;
388404 const canImport = ! ! ( pxt . appTarget . compile || ( pxt . appTarget . cloud && pxt . appTarget . cloud . sharing && pxt . appTarget . cloud . importing ) ) ;
389405
390406 // lf("Make")
@@ -472,7 +488,7 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
472488 label = { scr . label }
473489 labelClass = { scr . labelClass }
474490 tags = { scr . tags }
475- scr = { ( scr as pxt . CodeCard & { projectHeader ?: pxt . workspace . Header } ) . projectHeader || scr } index = { index }
491+ scr = { scr . projectHeader || scr } index = { index }
476492 onCardClick = { this . handleSearchCardClick }
477493 cardType = { scr . cardType }
478494 time = { scr . time }
@@ -486,7 +502,7 @@ export class Projects extends auth.Component<ISettingsProps, ProjectsState> {
486502 < ProjectsDetail parent = { this . props . parent }
487503 name = { selectedSearchCard . name }
488504 key = { 'detailsearch' + selectedSearchCard . name }
489- description = { selectedSearchCard . description }
505+ description = { selectedSearchDescription }
490506 url = { selectedSearchCard . url }
491507 imageUrl = { selectedSearchCard . imageUrl }
492508 largeImageUrl = { selectedSearchCard . largeImageUrl }
0 commit comments