Back button for search suggestions and no results screen when searching (#1615)

Back button for search suggestions and no results screen when searching
This commit is contained in:
Vishnu Mohandas 2023-12-20 19:33:39 +05:30 committed by GitHub
commit 6e97c4bac4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 185 additions and 154 deletions

View file

@ -0,0 +1,3 @@
import 'package:photos/events/event.dart';
class ClearAndUnfocusSearchBar extends Event {}

View file

@ -40,18 +40,15 @@ class _SearchTabState extends State<SearchTab> {
@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<AllSearchSections> {
// 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();
},
),
],
),
);
}
}

View file

@ -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";

View file

@ -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<NoResultWidget> {
);
},
);
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,
),
),
],
),
),
);
}

View file

@ -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<SearchSuffixIcon>
splashRadius: 1,
visualDensity: const VisualDensity(horizontal: -1, vertical: -1),
onPressed: () {
final searchWidgetState =
context.findAncestorStateOfType<SearchWidgetState>()!;
searchWidgetState.textController.clear();
searchWidgetState.focusNode.unfocus();
Bus.instance.fire(ClearAndUnfocusSearchBar());
},
icon: Icon(
Icons.close,

View file

@ -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(),
),
),
),
],
],
),
),
);
}

View file

@ -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<SearchWidget> {
double _distanceOfWidgetFromBottom = 0;
GlobalKey widgetKey = GlobalKey();
TextEditingController textController = TextEditingController();
late final StreamSubscription<ClearAndUnfocusSearchBar>
_clearAndUnfocusSearchBar;
@override
void initState() {
@ -62,6 +65,12 @@ class SearchWidgetState extends State<SearchWidget> {
textController.addListener(textControllerListener);
});
textController.text = query;
_clearAndUnfocusSearchBar =
Bus.instance.on<ClearAndUnfocusSearchBar>().listen((event) {
textController.clear();
focusNode.unfocus();
});
}
@override
@ -81,6 +90,7 @@ class SearchWidgetState extends State<SearchWidget> {
_tabDoubleTapEvent?.cancel();
textController.removeListener(textControllerListener);
textController.dispose();
_clearAndUnfocusSearchBar.cancel();
super.dispose();
}