import "package:dotted_border/dotted_border.dart"; import "package:flutter/material.dart"; import "package:photos/models/search/recent_searches.dart"; import "package:photos/models/search/search_result.dart"; import "package:photos/models/search/search_types.dart"; import "package:photos/theme/ente_theme.dart"; import "package:photos/ui/components/buttons/icon_button_widget.dart"; import "package:photos/ui/viewer/search/result/search_result_page.dart"; import "package:photos/ui/viewer/search/result/search_thumbnail_widget.dart"; import "package:photos/utils/navigation_util.dart"; class SearchableItemWidget extends StatelessWidget { final SearchResult searchResult; final Future? resultCount; final Function? onResultTap; const SearchableItemWidget( this.searchResult, { Key? key, this.resultCount, this.onResultTap, }) : super(key: key); @override Widget build(BuildContext context) { final heroTagPrefix = searchResult.heroTag(); final textTheme = getEnteTextTheme(context); final colorScheme = getEnteColorScheme(context); return GestureDetector( onTap: () { RecentSearches().add(searchResult); if (onResultTap != null) { onResultTap!(); } else { routeToPage( context, SearchResultPage(searchResult), ); } }, child: Container( decoration: BoxDecoration( border: Border.all(color: colorScheme.strokeFainter), borderRadius: const BorderRadius.all( Radius.circular(4), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( flex: 6, child: Row( children: [ SizedBox( width: 60, height: 60, child: SearchThumbnailWidget( searchResult.previewThumbnail(), heroTagPrefix, ), ), const SizedBox(width: 12), Flexible( child: Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( searchResult.name(), style: textTheme.body, overflow: TextOverflow.ellipsis, ), const SizedBox( height: 2, ), FutureBuilder( future: resultCount ?? Future.value(searchResult.resultFiles().length), builder: (context, snapshot) { if (snapshot.hasData && snapshot.data! > 0) { final noOfMemories = snapshot.data; final String suffix = noOfMemories! > 1 ? " memories" : " memory"; return Text( noOfMemories.toString() + suffix, style: textTheme.smallMuted, ); } else { return const SizedBox.shrink(); } }, ), ], ), ), ), ], ), ), const Flexible( flex: 1, child: IconButtonWidget( icon: Icons.chevron_right_outlined, iconButtonType: IconButtonType.secondary, ), ), ], ), ), ); } } class SearchableItemPlaceholder extends StatelessWidget { final SectionType sectionType; const SearchableItemPlaceholder(this.sectionType, {super.key}); @override Widget build(BuildContext context) { if (sectionType.isCTAVisible == false) { return const SizedBox.shrink(); } final colorScheme = getEnteColorScheme(context); final textTheme = getEnteTextTheme(context); return Padding( padding: const EdgeInsets.only(right: 1), child: GestureDetector( onTap: sectionType.ctaOnTap(context), child: DottedBorder( strokeWidth: 2, borderType: BorderType.RRect, radius: const Radius.circular(4), padding: EdgeInsets.zero, dashPattern: const [4, 4], color: colorScheme.strokeFainter, child: Row( children: [ Container( width: 60, height: 60, decoration: BoxDecoration( borderRadius: const BorderRadius.horizontal(left: Radius.circular(4)), color: colorScheme.fillFaint, ), child: Icon( sectionType.getCTAIcon(), color: colorScheme.strokeMuted, ), ), const SizedBox(width: 12), Text( sectionType.getCTAText(context), style: textTheme.body, ), ], ), ), ), ); } }