From ea0d2584f3b460b93a3de8215b9eae455305ee66 Mon Sep 17 00:00:00 2001 From: Frederik Feichtmeier Date: Sun, 19 Jun 2022 22:02:30 +0200 Subject: [PATCH] Improve search UI (#45) --- lib/l10n/app_en.arb | 2 +- lib/store_app/explore/explore_model.dart | 15 ++++++- lib/store_app/explore/explore_page.dart | 10 ++++- lib/store_app/explore/search_field.dart | 44 ++++++++++++------- .../explore/section_banner_grid.dart | 35 +++++++-------- linux/my_application.cc | 2 +- 6 files changed, 69 insertions(+), 39 deletions(-) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index d8d6c65a1..130103598 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -53,7 +53,7 @@ "media": "Media", "done": "Done", "systemUpdates": "System updates", - "searchHint": "Search...", + "searchHint": "Search", "updateAll": "Update all", "noUpdates": "No updates available" } \ No newline at end of file diff --git a/lib/store_app/explore/explore_model.dart b/lib/store_app/explore/explore_model.dart index 3937c7b60..f6eb92e81 100644 --- a/lib/store_app/explore/explore_model.dart +++ b/lib/store_app/explore/explore_model.dart @@ -11,7 +11,8 @@ class ExploreModel extends SafeChangeNotifier { this.client, ) : _searchQuery = '', sectionNameToSnapsMap = {}, - _errorMessage = ''; + _errorMessage = '', + _searchActive = false; String _errorMessage; String get errorMessage => _errorMessage; @@ -25,6 +26,17 @@ class ExploreModel extends SafeChangeNotifier { notifyListeners(); } + bool _searchActive; + bool get searchActive => _searchActive; + set searchActive(bool value) { + if (value == _searchActive) return; + _searchActive = value; + if (_searchActive == false) { + searchQuery = ''; + } + notifyListeners(); + } + String _searchQuery; String get searchQuery => _searchQuery; set searchQuery(String value) { @@ -39,6 +51,7 @@ class ExploreModel extends SafeChangeNotifier { set selectedSection(SnapSection value) { if (value == _selectedSection) return; _selectedSection = value; + loadSection(value); } Future> findSnapsByQuery() async { diff --git a/lib/store_app/explore/explore_page.dart b/lib/store_app/explore/explore_page.dart index 8396c4d00..ed572eafd 100644 --- a/lib/store_app/explore/explore_page.dart +++ b/lib/store_app/explore/explore_page.dart @@ -9,6 +9,7 @@ import 'package:software/store_app/explore/search_page.dart'; import 'package:software/store_app/explore/section_banner_grid.dart'; import 'package:software/store_app/explore/snap_banner_carousel.dart'; import 'package:ubuntu_service/ubuntu_service.dart'; +import 'package:yaru_icons/yaru_icons.dart'; import 'package:yaru_widgets/yaru_widgets.dart'; class ExplorePage extends StatelessWidget { @@ -31,7 +32,14 @@ class ExplorePage extends StatelessWidget { final model = context.watch(); return Scaffold( appBar: AppBar( - flexibleSpace: const SearchField(), + title: !model.searchActive + ? YaruRoundToggleButton( + selected: model.searchActive, + iconData: YaruIcons.search, + onPressed: () => model.searchActive = !model.searchActive, + ) + : null, + flexibleSpace: !model.searchActive ? null : const SearchField(), ), body: Padding( padding: const EdgeInsets.only(top: 20), diff --git a/lib/store_app/explore/search_field.dart b/lib/store_app/explore/search_field.dart index 071637dab..dd684e580 100644 --- a/lib/store_app/explore/search_field.dart +++ b/lib/store_app/explore/search_field.dart @@ -30,19 +30,26 @@ class _SearchFieldState extends State { onChanged: (value) => model.searchQuery = value, autofocus: true, decoration: InputDecoration( - hintText: context.l10n.searchHint, + hintText: + '${context.l10n.searchHint} ${model.selectedSection.localize(context.l10n)} snaps', suffixIcon: _SectionDropdown( value: model.selectedSection, - onChanged: (v) { - model.selectedSection = v!; - model.loadSection(v); - }, + onChanged: (v) => model.selectedSection = v!, ), prefixIconConstraints: const BoxConstraints(minWidth: 20), prefixIcon: model.searchQuery == '' - ? const SizedBox() + ? Padding( + padding: const EdgeInsets.only(left: 5, right: 5), + child: YaruRoundIconButton( + size: 36, + onTap: () { + model.searchActive = false; + }, + child: const Icon(YaruIcons.go_previous), + ), + ) : Padding( - padding: const EdgeInsets.only(left: 5), + padding: const EdgeInsets.only(left: 5, right: 5), child: YaruRoundIconButton( size: 36, onTap: () { @@ -75,14 +82,19 @@ class _SectionDropdown extends StatelessWidget { @override Widget build(BuildContext context) { - return DropdownButtonHideUnderline( - child: DropdownButton( + return PopupMenuButton( + splashRadius: 20, + onSelected: onChanged, + icon: Icon(snapSectionToIcon[value]), + initialValue: SnapSection.all, + shape: OutlineInputBorder( borderRadius: BorderRadius.circular(10), - elevation: 2, - value: value, - items: [ + borderSide: BorderSide(color: Theme.of(context).dividerColor, width: 1), + ), + itemBuilder: (context) { + return [ for (final section in SnapSection.values) - DropdownMenuItem( + PopupMenuItem( value: section, child: Row( mainAxisAlignment: MainAxisAlignment.end, @@ -113,10 +125,8 @@ class _SectionDropdown extends StatelessWidget { ], ), ) - ], - onChanged: onChanged, - // style: Theme.of(context).textTheme.title, - ), + ]; + }, ); } } diff --git a/lib/store_app/explore/section_banner_grid.dart b/lib/store_app/explore/section_banner_grid.dart index c71fe08c3..4b98595b0 100644 --- a/lib/store_app/explore/section_banner_grid.dart +++ b/lib/store_app/explore/section_banner_grid.dart @@ -31,28 +31,27 @@ class _SectionBannerGridState extends State { @override Widget build(BuildContext context) { final model = context.watch(); - final sections = model.sectionNameToSnapsMap[widget.snapSection.title]; - + final sections = + model.sectionNameToSnapsMap[widget.snapSection.title] ?? []; + if (sections.isEmpty) return const SizedBox(); return GridView( padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20), shrinkWrap: true, gridDelegate: kGridDelegate, - children: sections != null && sections.isNotEmpty - ? sections.take(widget.amount).map((snap) { - return AppBanner( - name: snap.name, - summary: snap.summary, - url: snap.iconUrl, - onTap: () => showDialog( - context: context, - builder: (context) => SnapDialog.create( - context: context, - huskSnapName: snap.name, - ), - ), - ); - }).toList() - : [], + children: sections.take(widget.amount).map((snap) { + return AppBanner( + name: snap.name, + summary: snap.summary, + url: snap.iconUrl, + onTap: () => showDialog( + context: context, + builder: (context) => SnapDialog.create( + context: context, + huskSnapName: snap.name, + ), + ), + ); + }).toList(), ); } } diff --git a/linux/my_application.cc b/linux/my_application.cc index 77fd71202..7d0be8d8e 100644 --- a/linux/my_application.cc +++ b/linux/my_application.cc @@ -54,7 +54,7 @@ static void my_application_activate(GApplication* application) { gtk_window_set_geometry_hints(window, nullptr, &geometry_min, GDK_HINT_MIN_SIZE); - gtk_window_set_default_size(window, 990, 920); + gtk_window_set_default_size(window, 800, 730); g_autoptr(FlDartProject) project = fl_dart_project_new(); fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);