diff --git a/lib/events/clear_and_unfocus_search_bar_event.dart b/lib/events/clear_and_unfocus_search_bar_event.dart new file mode 100644 index 000000000..3c7d9c91d --- /dev/null +++ b/lib/events/clear_and_unfocus_search_bar_event.dart @@ -0,0 +1,3 @@ +import 'package:photos/events/event.dart'; + +class ClearAndUnfocusSearchBar extends Event {} diff --git a/lib/ui/search_tab.dart b/lib/ui/search_tab.dart index a54a131f6..2392619d7 100644 --- a/lib/ui/search_tab.dart +++ b/lib/ui/search_tab.dart @@ -40,18 +40,15 @@ class _SearchTabState extends State { @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(top: 8), - child: AllSectionsExamplesProvider( - child: FadeIndexedStack( - duration: const Duration(milliseconds: 150), - index: index, - children: [ - const AllSearchSections(), - SearchSuggestionsWidget(_searchResults), - const NoResultWidget(), - ], - ), + return AllSectionsExamplesProvider( + child: FadeIndexedStack( + duration: const Duration(milliseconds: 150), + index: index, + children: [ + const AllSearchSections(), + SearchSuggestionsWidget(_searchResults), + const NoResultWidget(), + ], ), ); } @@ -71,58 +68,61 @@ class _AllSearchSectionsState extends State { // remove face and content sectionType searchTypes.remove(SectionType.face); searchTypes.remove(SectionType.content); - return Stack( - children: [ - FutureBuilder( - future: InheritedAllSectionsExamples.of(context) - .allSectionsExamplesFuture, - builder: (context, snapshot) { - if (snapshot.hasData) { - if (snapshot.data!.every((element) => element.isEmpty)) { + return Padding( + padding: const EdgeInsets.only(top: 8), + child: Stack( + children: [ + FutureBuilder( + future: InheritedAllSectionsExamples.of(context) + .allSectionsExamplesFuture, + builder: (context, snapshot) { + if (snapshot.hasData) { + if (snapshot.data!.every((element) => element.isEmpty)) { + return const Padding( + padding: EdgeInsets.only(bottom: 72), + child: SearchTabEmptyState(), + ); + } + return ListView.builder( + padding: const EdgeInsets.only(bottom: 180), + physics: const BouncingScrollPhysics(), + itemCount: searchTypes.length, + itemBuilder: (context, index) { + return SearchSection( + sectionType: searchTypes[index], + examples: snapshot.data!.elementAt(index), + limit: searchSectionLimit, + ); + }, + ); + } else if (snapshot.hasError) { + //Errors are handled and this else if condition will be false always + //is the understanding. return const Padding( padding: EdgeInsets.only(bottom: 72), - child: SearchTabEmptyState(), + child: EnteLoadingWidget(), + ); + } else { + return const Padding( + padding: EdgeInsets.only(bottom: 72), + child: EnteLoadingWidget(), ); } - return ListView.builder( - padding: const EdgeInsets.only(bottom: 180), - physics: const BouncingScrollPhysics(), - itemCount: searchTypes.length, - itemBuilder: (context, index) { - return SearchSection( - sectionType: searchTypes[index], - examples: snapshot.data!.elementAt(index), - limit: searchSectionLimit, - ); - }, - ); - } else if (snapshot.hasError) { - //Errors are handled and this else if condition will be false always - //is the understanding. - return const Padding( - padding: EdgeInsets.only(bottom: 72), - child: EnteLoadingWidget(), - ); - } else { - return const Padding( - padding: EdgeInsets.only(bottom: 72), - child: EnteLoadingWidget(), - ); - } - }, - ), - ValueListenableBuilder( - valueListenable: - InheritedAllSectionsExamples.of(context).isDebouncingNotifier, - builder: (context, value, _) { - return value - ? const EnteLoadingWidget( - alignment: Alignment.topRight, - ) - : const SizedBox.shrink(); - }, - ), - ], + }, + ), + ValueListenableBuilder( + valueListenable: + InheritedAllSectionsExamples.of(context).isDebouncingNotifier, + builder: (context, value, _) { + return value + ? const EnteLoadingWidget( + alignment: Alignment.topRight, + ) + : const SizedBox.shrink(); + }, + ), + ], + ), ); } } diff --git a/lib/ui/viewer/search/result/go_to_map_widget.dart b/lib/ui/viewer/search/result/go_to_map_widget.dart index 29f970858..fb449d824 100644 --- a/lib/ui/viewer/search/result/go_to_map_widget.dart +++ b/lib/ui/viewer/search/result/go_to_map_widget.dart @@ -1,5 +1,3 @@ -import "dart:async"; - import "package:flutter/material.dart"; import "package:photos/generated/l10n.dart"; import "package:photos/services/search_service.dart"; diff --git a/lib/ui/viewer/search/result/no_result_widget.dart b/lib/ui/viewer/search/result/no_result_widget.dart index 10c7b9dce..a15f616a7 100644 --- a/lib/ui/viewer/search/result/no_result_widget.dart +++ b/lib/ui/viewer/search/result/no_result_widget.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import "package:photos/core/event_bus.dart"; +import "package:photos/events/clear_and_unfocus_search_bar_event.dart"; import "package:photos/generated/l10n.dart"; import "package:photos/models/search/search_types.dart"; import "package:photos/states/all_sections_examples_state.dart"; @@ -71,42 +73,51 @@ class _NoResultWidgetState extends State { ); }, ); - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 32), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - S.of(context).noResultsFound, - style: textTheme.largeBold, - ), - const SizedBox(height: 6), - searchTypeToQuerySuggestion.isNotEmpty - ? Text( - S.of(context).modifyYourQueryOrTrySearchingFor, - style: textTheme.smallMuted, - ) - : const SizedBox.shrink(), - ], - ), - const SizedBox(height: 20), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: ListView.separated( - itemBuilder: (context, index) { - return searchTypeAndSuggestion[index]; - }, - separatorBuilder: (context, index) { - return const SizedBox(height: 12); - }, - itemCount: searchTypeToQuerySuggestion.length, - shrinkWrap: true, + return Scaffold( + appBar: AppBar( + leading: BackButton( + onPressed: () { + Bus.instance.fire(ClearAndUnfocusSearchBar()); + }, + ), + ), + body: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + S.of(context).noResultsFound, + style: textTheme.largeBold, + ), + const SizedBox(height: 6), + searchTypeToQuerySuggestion.isNotEmpty + ? Text( + S.of(context).modifyYourQueryOrTrySearchingFor, + style: textTheme.smallMuted, + ) + : const SizedBox.shrink(), + ], ), - ), - ], + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: ListView.separated( + itemBuilder: (context, index) { + return searchTypeAndSuggestion[index]; + }, + separatorBuilder: (context, index) { + return const SizedBox(height: 12); + }, + itemCount: searchTypeToQuerySuggestion.length, + shrinkWrap: true, + ), + ), + ], + ), ), ); } diff --git a/lib/ui/viewer/search/search_suffix_icon_widget.dart b/lib/ui/viewer/search/search_suffix_icon_widget.dart index c8f034fb1..f5d36f499 100644 --- a/lib/ui/viewer/search/search_suffix_icon_widget.dart +++ b/lib/ui/viewer/search/search_suffix_icon_widget.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; +import "package:photos/core/event_bus.dart"; +import "package:photos/events/clear_and_unfocus_search_bar_event.dart"; import "package:photos/theme/ente_theme.dart"; -import 'package:photos/ui/viewer/search/search_widget.dart'; class SearchSuffixIcon extends StatefulWidget { final bool shouldShowSpinner; @@ -35,10 +36,7 @@ class _SearchSuffixIconState extends State splashRadius: 1, visualDensity: const VisualDensity(horizontal: -1, vertical: -1), onPressed: () { - final searchWidgetState = - context.findAncestorStateOfType()!; - searchWidgetState.textController.clear(); - searchWidgetState.focusNode.unfocus(); + Bus.instance.fire(ClearAndUnfocusSearchBar()); }, icon: Icon( Icons.close, diff --git a/lib/ui/viewer/search/search_suggestions.dart b/lib/ui/viewer/search/search_suggestions.dart index d4dda4b8b..22f6f76bd 100644 --- a/lib/ui/viewer/search/search_suggestions.dart +++ b/lib/ui/viewer/search/search_suggestions.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; +import "package:photos/core/event_bus.dart"; +import "package:photos/events/clear_and_unfocus_search_bar_event.dart"; import "package:photos/generated/l10n.dart"; import 'package:photos/models/search/album_search_result.dart'; import 'package:photos/models/search/generic_search_result.dart'; @@ -23,62 +25,71 @@ class SearchSuggestionsWidget extends StatelessWidget { late final String title; final resultsCount = results.length; title = S.of(context).searchResultCount(resultsCount); - return Padding( - padding: const EdgeInsets.fromLTRB(12, 32, 12, 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: getEnteTextTheme(context).largeBold, - ), - const SizedBox(height: 20), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: ListView.separated( - itemBuilder: (context, index) { - final result = results[index]; - if (result is AlbumSearchResult) { - final AlbumSearchResult albumSearchResult = result; - return SearchResultWidget( - result, - resultCount: CollectionsService.instance.getFileCount( - albumSearchResult.collectionWithThumbnail.collection, - ), - onResultTap: () => routeToPage( - context, - CollectionPage( - albumSearchResult.collectionWithThumbnail, - tagPrefix: result.heroTag(), + return Scaffold( + appBar: AppBar( + leading: BackButton( + onPressed: () { + Bus.instance.fire(ClearAndUnfocusSearchBar()); + }, + ), + ), + body: Padding( + padding: const EdgeInsets.fromLTRB(12, 0, 12, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: getEnteTextTheme(context).largeBold, + ), + const SizedBox(height: 20), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: ListView.separated( + itemBuilder: (context, index) { + final result = results[index]; + if (result is AlbumSearchResult) { + final AlbumSearchResult albumSearchResult = result; + return SearchResultWidget( + result, + resultCount: CollectionsService.instance.getFileCount( + albumSearchResult.collectionWithThumbnail.collection, ), - ), - ); - } else if (result is GenericSearchResult) { - return SearchResultWidget( - result, - onResultTap: result.onResultTap != null - ? () => result.onResultTap!(context) - : null, - ); - } else { - Logger('SearchSuggestionsWidget') - .info("Invalid/Unsupported value"); - return const SizedBox.shrink(); - } - }, - padding: EdgeInsets.only( - bottom: (MediaQuery.sizeOf(context).height / 2) + 50, + onResultTap: () => routeToPage( + context, + CollectionPage( + albumSearchResult.collectionWithThumbnail, + tagPrefix: result.heroTag(), + ), + ), + ); + } else if (result is GenericSearchResult) { + return SearchResultWidget( + result, + onResultTap: result.onResultTap != null + ? () => result.onResultTap!(context) + : null, + ); + } else { + Logger('SearchSuggestionsWidget') + .info("Invalid/Unsupported value"); + return const SizedBox.shrink(); + } + }, + padding: EdgeInsets.only( + bottom: (MediaQuery.sizeOf(context).height / 2) + 50, + ), + separatorBuilder: (context, index) { + return const SizedBox(height: 12); + }, + itemCount: results.length, + physics: const BouncingScrollPhysics(), ), - separatorBuilder: (context, index) { - return const SizedBox(height: 12); - }, - itemCount: results.length, - physics: const BouncingScrollPhysics(), ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/ui/viewer/search/search_widget.dart b/lib/ui/viewer/search/search_widget.dart index 7cff2fc38..133f98e7e 100644 --- a/lib/ui/viewer/search/search_widget.dart +++ b/lib/ui/viewer/search/search_widget.dart @@ -4,6 +4,7 @@ import "package:flutter/material.dart"; import "package:flutter/scheduler.dart"; import "package:logging/logging.dart"; import "package:photos/core/event_bus.dart"; +import "package:photos/events/clear_and_unfocus_search_bar_event.dart"; import "package:photos/events/tab_changed_event.dart"; import "package:photos/models/search/search_result.dart"; import "package:photos/services/search_service.dart"; @@ -33,6 +34,8 @@ class SearchWidgetState extends State { double _distanceOfWidgetFromBottom = 0; GlobalKey widgetKey = GlobalKey(); TextEditingController textController = TextEditingController(); + late final StreamSubscription + _clearAndUnfocusSearchBar; @override void initState() { @@ -62,6 +65,12 @@ class SearchWidgetState extends State { textController.addListener(textControllerListener); }); textController.text = query; + + _clearAndUnfocusSearchBar = + Bus.instance.on().listen((event) { + textController.clear(); + focusNode.unfocus(); + }); } @override @@ -81,6 +90,7 @@ class SearchWidgetState extends State { _tabDoubleTapEvent?.cancel(); textController.removeListener(textControllerListener); textController.dispose(); + _clearAndUnfocusSearchBar.cancel(); super.dispose(); }